From 5b30797592bf5f1619a093368038bf71f3f6fd1f Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 12 Nov 2019 16:16:40 +0000 Subject: [PATCH 001/322] Blazor WebAssembly move to netstandard2.1 (#16808) * Now works on ns2.1, but links too much * Now only link System.* assemblies * Clean up. Also link Microsoft.Extensions.* now too, since it works. * x-plat slash consistency * Change all Blazor.* projects to netstandard2.1 * Further TFM updates * Stop linking Microsoft.Extensions for now, since it requires a more detailed treatment to avoid breaking things --- .../ref/Microsoft.AspNetCore.Blazor.csproj | 6 +++--- ...rosoft.AspNetCore.Blazor.netstandard2.1.cs} | 0 .../src/Microsoft.AspNetCore.Blazor.csproj | 2 +- .../src/targets/Blazor.MonoRuntime.targets | 18 +++++++++++++++--- ...crosoft.AspNetCore.Blazor.HttpClient.csproj | 6 +++--- ...etCore.Blazor.HttpClient.netstandard2.1.cs} | 0 ...crosoft.AspNetCore.Blazor.HttpClient.csproj | 2 +- .../Client/BlazorWasm-CSharp.Client.csproj | 2 +- .../Shared/BlazorWasm-CSharp.Shared.csproj | 2 +- ...re.Blazor.DataAnnotations.Validation.csproj | 2 +- .../HostedInAspNet.Client.csproj | 2 +- ...oft.AspNetCore.Blazor.E2EPerformance.csproj | 2 +- .../MonoSanityClient/MonoSanityClient.csproj | 2 +- .../StandaloneApp/StandaloneApp.csproj | 2 +- .../BasicTestApp/BasicTestApp.csproj | 2 +- 15 files changed, 31 insertions(+), 19 deletions(-) rename src/Components/Blazor/Blazor/ref/{Microsoft.AspNetCore.Blazor.netstandard2.0.cs => Microsoft.AspNetCore.Blazor.netstandard2.1.cs} (100%) rename src/Components/Blazor/Http/ref/{Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.0.cs => Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs} (100%) diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj index d750edc189a8..88ca078caaeb 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj @@ -1,10 +1,10 @@ - netstandard2.0 + netstandard2.1 - - + + diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs similarity index 100% rename from src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs rename to src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs diff --git a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj index 0673c85b2d23..be94e420a214 100644 --- a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 Build client-side single-page applications (SPAs) with Blazor running under WebAssembly. true diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 69976d519b68..b2de5481db3c 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -421,11 +421,23 @@ has changed. 4) Add the file we just created to the list of file writes, to support incremental builds. --> + + <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)"> + $([System.String]::Copy('%(RelativeDir)').TrimEnd('\').TrimEnd('/')) + true + + <_MonoBaseClassLibraryFolder Include="$(MonoBaseClassLibraryPath);$(MonoBaseClassLibraryFacadesPath);$(MonoWasmFrameworkPath)" /> - <_BlazorAssembliesToLink Include="@(_BlazorDependencyInput->'-a "%(Identity)"')" /> - <_BlazorAssembliesToLink Include="@(IntermediateAssembly->'-a "%(FullPath)"')" /> + <_BlazorAssembliesToCopy Include="@(IntermediateAssembly->'-a "%(FullPath)"')" /> <_BlazorFolderLookupPaths Include="@(_MonoBaseClassLibraryFolder->'-d "%(Identity)"')" /> + + + <_BlazorFolderLookupPaths Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" Include="@(_BlazorDependencyAssembly->'-d "%(RelativeDirNoTrailingSlash)"')" /> + + + <_BlazorAssembliesToCopy Condition="'%(_BlazorDependencyAssembly.IsLinkable)' != 'true'" Include="@(_BlazorDependencyAssembly->'-a "%(FullPath)"')" /> + <_BlazorAssemblyDescriptorFiles Include="@(BlazorLinkerDescriptor->'-x "%(FullPath)"')" Condition="'@(BlazorLinkerDescriptor)' != ''" /> @@ -438,7 +450,7 @@ - + diff --git a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj index 8c5f6d9e136c..6a3ca4305dae 100644 --- a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj +++ b/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj @@ -1,10 +1,10 @@ - netstandard2.0 + netstandard2.1 - - + + diff --git a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.0.cs b/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs similarity index 100% rename from src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.0.cs rename to src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs diff --git a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj index 18bdc5e1fe28..be140d936e27 100644 --- a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj +++ b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly. true diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj index c4eb65bded24..c855c49821f3 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 3.0 diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj index 2a77f0c7cc91..d849ca903629 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 7.3 diff --git a/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj b/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj index a166d5f1f3d1..725b1f981114 100644 --- a/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj +++ b/src/Components/Blazor/Validation/src/Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 Provides experimental support for validation using DataAnnotations. true false diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj index ef12ac3c4e83..cb21b79a8c0b 100644 --- a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj +++ b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 Exe true 3.0 diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj b/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj index 9f796fdbcf9c..140762810fb5 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj +++ b/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 true 3.0 diff --git a/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj b/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj index b186c391941b..e01c60084327 100644 --- a/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj +++ b/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 false false exe diff --git a/src/Components/Blazor/testassets/StandaloneApp/StandaloneApp.csproj b/src/Components/Blazor/testassets/StandaloneApp/StandaloneApp.csproj index cddd429b6a40..32156c56b854 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/StandaloneApp.csproj +++ b/src/Components/Blazor/testassets/StandaloneApp/StandaloneApp.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 true 3.0 diff --git a/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj b/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj index 98357d0e8835..9914ec452179 100644 --- a/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj +++ b/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 3.0 true From 23f9a9ea13d04ae165c3fd7a987a502c3e68fd64 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Wed, 13 Nov 2019 18:06:37 -0800 Subject: [PATCH 002/322] Revert "Keep Blazor at pre-release for 3.1" This reverts commit e7e29105ccb1ede074052b8460474b8836c0a27f. --- eng/Versions.props | 3 --- src/Components/Blazor/Directory.Build.props | 9 --------- 2 files changed, 12 deletions(-) delete mode 100644 src/Components/Blazor/Directory.Build.props diff --git a/eng/Versions.props b/eng/Versions.props index 09645f97c466..93c01fb584f3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -19,9 +19,6 @@ false preview$(PreReleasePreviewNumber) Preview $(PreReleasePreviewNumber) - - 4 - preview$(BlazorClientPreReleasePreviewNumber) $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) false diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props deleted file mode 100644 index a90d83b4cc93..000000000000 --- a/src/Components/Blazor/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - $(BlazorClientPreReleaseVersionLabel) - - - From a53addc1fea197707a1a283868862c46bb2b95c0 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Wed, 13 Nov 2019 18:09:42 -0800 Subject: [PATCH 003/322] Revert dependency updates from 3.1 merge --- NuGet.config | 5 - eng/Version.Details.xml | 400 ++++++++++++++++++++-------------------- eng/Versions.props | 202 ++++++++++---------- 3 files changed, 301 insertions(+), 306 deletions(-) diff --git a/NuGet.config b/NuGet.config index 362df7f886a0..5d28b80a6f15 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,12 +3,7 @@ - - - - - diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1b253097c41c..54509fa0331e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,393 +9,393 @@ --> - + https://github.com/aspnet/Blazor - c8cc48b96c4ef3405dfc1678b089650aec2845ff + df77420cad90b1834fe43c952861dad11097d38f - + https://github.com/aspnet/AspNetCore-Tooling - d29aca1669a58a198445845c53a1e5792d6a6593 + 542a22f0b0242fc7247884b316c71e921d9711da - + https://github.com/aspnet/AspNetCore-Tooling - d29aca1669a58a198445845c53a1e5792d6a6593 + 542a22f0b0242fc7247884b316c71e921d9711da - + https://github.com/aspnet/AspNetCore-Tooling - d29aca1669a58a198445845c53a1e5792d6a6593 + 542a22f0b0242fc7247884b316c71e921d9711da - + https://github.com/aspnet/AspNetCore-Tooling - d29aca1669a58a198445845c53a1e5792d6a6593 + 542a22f0b0242fc7247884b316c71e921d9711da - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/EntityFrameworkCore - 593a3807085dab72170dba95f9283e244961f5db + 3442750627d3532f4e44f21df91f7fbe9315e59a - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/dotnet/core-setup - b7dc9ed2f7ec52c7c3df94a89c7c3b22431c9d33 + 13f35c3d86a40ff811bfde0b64cfb86431c19d15 - + https://github.com/dotnet/core-setup - b7dc9ed2f7ec52c7c3df94a89c7c3b22431c9d33 + 13f35c3d86a40ff811bfde0b64cfb86431c19d15 - + https://github.com/dotnet/core-setup - b7dc9ed2f7ec52c7c3df94a89c7c3b22431c9d33 + 13f35c3d86a40ff811bfde0b64cfb86431c19d15 https://github.com/dotnet/core-setup @@ -404,13 +404,13 @@ - + https://github.com/dotnet/corefx - 4703e4aefb6650500d00a2a529c7ad474ca89859 + 046765913dff824f9ed0f2d2fe0fb9b111906cf5 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 https://github.com/dotnet/arcade @@ -424,13 +424,13 @@ https://github.com/dotnet/arcade a42a124635ce1a218309ecb31ec59d559cacb886 - + https://github.com/aspnet/Extensions - c273f3c664433d1b6dd2c107adaf8270e9448c01 + 02e6d683074019728bfbda8e40e526606fd12875 - + https://github.com/dotnet/roslyn - 1cb14195ed43eefdf7f9de59140ff6db70eea76e + dd838b6fc2ed66913ad99a1a7d58b1b1c07530ed diff --git a/eng/Versions.props b/eng/Versions.props index 93c01fb584f3..fd988d11b4ee 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -13,7 +13,7 @@ - true + false release true false @@ -64,114 +64,114 @@ 1.0.0-beta.19517.3 - 3.4.0-beta4-19562-01 + 3.5.0-beta1-19551-03 - 3.1.0 - 3.1.0 - 3.1.0 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 2.1.0 - 1.1.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 1.8.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 - 4.7.0 + 1.1.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 1.8.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 + 4.7.0-preview3.19551.4 - 3.1.0 + 3.1.0-preview3.19551.4 - 3.1.0-preview4.19562.1 + 3.1.0-preview3.19531.1 - 3.1.0-preview3.19562.4 - 3.1.0-preview3.19562.4 - 3.1.0-preview3.19562.4 - 3.1.0-preview3.19562.4 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0-preview3.19562.4 - 3.1.0 - 3.1.0-preview3.19562.4 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 + 3.1.0-preview3.19553.2 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 + 3.1.0-preview3.19554.8 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 + 3.1.0-preview3.19553.1 + 3.1.0-preview3.19553.1 + 3.1.0-preview3.19553.1 + 3.1.0-preview3.19553.1 + + + + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 54509fa0331e..e5f59d2cb63e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,373 +29,373 @@ https://github.com/aspnet/AspNetCore-Tooling 542a22f0b0242fc7247884b316c71e921d9711da - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/EntityFrameworkCore - 3442750627d3532f4e44f21df91f7fbe9315e59a + 988a8a13a524504ede374e2173651bd01f845c37 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/core-setup - 13f35c3d86a40ff811bfde0b64cfb86431c19d15 + 93ee64d467eeccd7006e370e78cf6dae31c1f3e2 - + https://github.com/dotnet/core-setup - 13f35c3d86a40ff811bfde0b64cfb86431c19d15 + 93ee64d467eeccd7006e370e78cf6dae31c1f3e2 - + https://github.com/dotnet/core-setup - 13f35c3d86a40ff811bfde0b64cfb86431c19d15 + 93ee64d467eeccd7006e370e78cf6dae31c1f3e2 https://github.com/dotnet/core-setup @@ -404,33 +404,33 @@ - + https://github.com/dotnet/corefx - 046765913dff824f9ed0f2d2fe0fb9b111906cf5 + 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/dotnet/arcade - a42a124635ce1a218309ecb31ec59d559cacb886 + e34d933e18ba1cd393bbafcb6018e0f858d3e89e - + https://github.com/dotnet/arcade - a42a124635ce1a218309ecb31ec59d559cacb886 + e34d933e18ba1cd393bbafcb6018e0f858d3e89e - + https://github.com/dotnet/arcade - a42a124635ce1a218309ecb31ec59d559cacb886 + e34d933e18ba1cd393bbafcb6018e0f858d3e89e - + https://github.com/aspnet/Extensions - 02e6d683074019728bfbda8e40e526606fd12875 + 4ebd75b961136c7ca331866eed3403becda75681 - + https://github.com/dotnet/roslyn - dd838b6fc2ed66913ad99a1a7d58b1b1c07530ed + 82f2e2541478e239dc4b04f231e90dc2b3dcb422 diff --git a/eng/Versions.props b/eng/Versions.props index fd988d11b4ee..4c61494afafc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,111 +62,111 @@ --> - 1.0.0-beta.19517.3 + 1.0.0-beta.19569.2 - 3.5.0-beta1-19551-03 + 3.4.0-beta4-19568-04 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 + 3.1.0 + 3.1.0 + 3.1.0 2.1.0 - 1.1.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 1.8.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 - 4.7.0-preview3.19551.4 + 1.1.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 1.8.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 + 4.7.0 - 3.1.0-preview3.19551.4 + 3.1.0 3.1.0-preview3.19531.1 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 - 3.1.0-preview3.19553.2 + 3.1.0-rtm.19568.3 + 3.1.0-rtm.19568.3 + 3.1.0-rtm.19568.3 + 3.1.0-rtm.19568.3 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0-rtm.19568.3 + 3.1.0 + 3.1.0-preview4.19568.3 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 - 3.1.0-preview3.19554.8 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-preview3.19553.1 3.1.0-preview3.19553.1 diff --git a/eng/common/post-build/setup-maestro-vars.ps1 b/eng/common/post-build/setup-maestro-vars.ps1 index 5668ef091a72..d7f64dc63cbc 100644 --- a/eng/common/post-build/setup-maestro-vars.ps1 +++ b/eng/common/post-build/setup-maestro-vars.ps1 @@ -6,12 +6,12 @@ param( try { $Content = Get-Content $ReleaseConfigsPath - + $BarId = $Content | Select -Index 0 - + $Channels = "" $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - + $IsStableBuild = $Content | Select -Index 2 Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId @@ -23,4 +23,4 @@ catch { Write-Host $_.Exception Write-Host $_.ScriptStackTrace ExitWithExitCode 1 -} \ No newline at end of file +} diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index a7f996419522..52e2ff021d70 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -6,6 +6,11 @@ parameters: # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter sdlContinueOnError: false # optional: determines whether to continue the build if the step errors; dependsOn: '' # Optional: dependencies of the job + artifactNames: '' # Optional: patterns supplied to DownloadBuildArtifacts + # Usage: + # artifactNames: + # - 'BlobArtifacts' + # - 'Artifacts_Windows_NT_Release' jobs: - job: Run_SDL @@ -18,13 +23,22 @@ jobs: steps: - checkout: self clean: true - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: current - downloadType: specific files - matchingPattern: "**" - downloadPath: $(Build.SourcesDirectory)\artifacts + - ${{ if ne(parameters.artifactNames, '') }}: + - ${{ each artifactName in parameters.artifactNames }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Build Artifacts + inputs: + buildType: current + artifactName: ${{ artifactName }} + downloadPath: $(Build.ArtifactStagingDirectory)\artifacts + - ${{ if eq(parameters.artifactNames, '') }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Build Artifacts + inputs: + buildType: current + downloadType: specific files + itemPattern: "**" + downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - powershell: eng/common/sdl/extract-artifact-packages.ps1 -InputPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts -ExtractPath $(Build.SourcesDirectory)\artifacts\BlobArtifacts diff --git a/eng/common/templates/post-build/channels/netcore-internal-30.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml similarity index 85% rename from eng/common/templates/post-build/channels/netcore-internal-30.yml rename to eng/common/templates/post-build/channels/generic-internal-channel.yml index 177b38df3571..68fdec029020 100644 --- a/eng/common/templates/post-build/channels/netcore-internal-30.yml +++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml @@ -1,20 +1,26 @@ parameters: + publishInstallersAndChecksums: false symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' + stageName: '' + channelName: '' + channelId: '' + transportFeed: '' + shippingFeed: '' + symbolsFeed: '' stages: -- stage: NetCore_30_Internal_Servicing_Publishing +- stage: ${{ parameters.stageName }} dependsOn: validate variables: - template: ../common-variables.yml - displayName: .NET Core 3.0 Internal Servicing Publishing + displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) variables: - group: DotNet-Symbol-Server-Pats pool: @@ -55,7 +61,7 @@ stages: value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }})) pool: vmImage: 'windows-2019' steps: @@ -115,14 +121,15 @@ stages: /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' + /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' + /p:PublishToMSDL=false ${{ parameters.artifactsPublishingAdditionalParameters }} - template: ../../steps/promote-build.yml parameters: - ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} + ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/netcore-release-31.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml similarity index 79% rename from eng/common/templates/post-build/channels/netcore-release-31.yml rename to eng/common/templates/post-build/channels/generic-public-channel.yml index 01d56410c7d4..c4bc1897d81f 100644 --- a/eng/common/templates/post-build/channels/netcore-release-31.yml +++ b/eng/common/templates/post-build/channels/generic-public-channel.yml @@ -1,21 +1,27 @@ parameters: - symbolPublishingAdditionalParameters: '' artifactsPublishingAdditionalParameters: '' publishInstallersAndChecksums: false + symbolPublishingAdditionalParameters: '' + stageName: '' + channelName: '' + channelId: '' + transportFeed: '' + shippingFeed: '' + symbolsFeed: '' stages: -- stage: NetCore_Release31_Publish +- stage: ${{ parameters.stageName }} dependsOn: validate variables: - template: ../common-variables.yml - displayName: .NET Core 3.1 Release Publishing + displayName: ${{ parameters.channelName }} Publishing jobs: - template: ../setup-maestro-vars.yml - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_31_Channel_Id)) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }} )) variables: - group: DotNet-Symbol-Server-Pats pool: @@ -33,6 +39,18 @@ stages: artifactName: 'PDBArtifacts' continueOnError: true + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@0 + displayName: 'Authenticate to AzDO Feeds' + + - task: PowerShell@2 + displayName: Enable cross-org publishing + inputs: + filePath: eng\common\enable-cross-org-publishing.ps1 + arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) + - task: PowerShell@2 displayName: Publish inputs: @@ -50,13 +68,11 @@ stages: displayName: Publish Assets dependsOn: setupMaestroVars variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_31_Channel_Id)) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.channelId }})) pool: vmImage: 'windows-2019' steps: @@ -65,12 +81,14 @@ stages: inputs: buildType: current artifactName: PackageArtifacts + continueOnError: true - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: buildType: current artifactName: BlobArtifacts + continueOnError: true - task: DownloadBuildArtifacts@0 displayName: Download Asset Manifests @@ -117,14 +135,14 @@ stages: /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' ${{ parameters.artifactsPublishingAdditionalParameters }} - template: ../../steps/promote-build.yml parameters: - ChannelId: ${{ variables.PublicRelease_31_Channel_Id }} + ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/netcore-3-tools-validation.yml b/eng/common/templates/post-build/channels/netcore-3-tools-validation.yml deleted file mode 100644 index cdb74031fcfc..000000000000 --- a/eng/common/templates/post-build/channels/netcore-3-tools-validation.yml +++ /dev/null @@ -1,95 +0,0 @@ -parameters: - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_3_Tools_Validation_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET 3 Tools - Validation Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NETCore_3_Tools_Validation_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.NETCore_3_Tools_Validation_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-3-tools.yml b/eng/common/templates/post-build/channels/netcore-3-tools.yml deleted file mode 100644 index 70eec773e750..000000000000 --- a/eng/common/templates/post-build/channels/netcore-3-tools.yml +++ /dev/null @@ -1,130 +0,0 @@ -parameters: - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_3_Tools_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET 3 Tools Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_3_Tools_Channel_Id)) - variables: - - group: DotNet-Symbol-Server-Pats - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts - inputs: - artifactName: 'PDBArtifacts' - continueOnError: true - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_3_Tools_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.NetCore_3_Tools_Channel_Id }} \ No newline at end of file diff --git a/eng/common/templates/post-build/channels/netcore-dev-31.yml b/eng/common/templates/post-build/channels/netcore-dev-31.yml deleted file mode 100644 index db21254187d9..000000000000 --- a/eng/common/templates/post-build/channels/netcore-dev-31.yml +++ /dev/null @@ -1,130 +0,0 @@ -parameters: - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_Dev31_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET Core 3.1 Dev Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_31_Channel_Id)) - variables: - - group: DotNet-Symbol-Server-Pats - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts - inputs: - artifactName: 'PDBArtifacts' - continueOnError: true - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_31_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.PublicDevRelease_31_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-dev-5.yml b/eng/common/templates/post-build/channels/netcore-dev-5.yml deleted file mode 100644 index c4f5a16acb62..000000000000 --- a/eng/common/templates/post-build/channels/netcore-dev-5.yml +++ /dev/null @@ -1,130 +0,0 @@ -parameters: - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_Dev5_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET Core 5 Dev Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) - variables: - - group: DotNet-Symbol-Server-Pats - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts - inputs: - artifactName: 'PDBArtifacts' - continueOnError: true - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-release-30.yml b/eng/common/templates/post-build/channels/netcore-release-30.yml deleted file mode 100644 index 16ade0db29de..000000000000 --- a/eng/common/templates/post-build/channels/netcore-release-30.yml +++ /dev/null @@ -1,130 +0,0 @@ -parameters: - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_Release30_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET Core 3.0 Release Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) - variables: - - group: DotNet-Symbol-Server-Pats - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts - inputs: - artifactName: 'PDBArtifacts' - continueOnError: true - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.PublicRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-tools-latest.yml b/eng/common/templates/post-build/channels/netcore-tools-latest.yml deleted file mode 100644 index 157d2d4b9772..000000000000 --- a/eng/common/templates/post-build/channels/netcore-tools-latest.yml +++ /dev/null @@ -1,130 +0,0 @@ -parameters: - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: NetCore_Tools_Latest_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET Tools - Latest Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) - variables: - - group: DotNet-Symbol-Server-Pats - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - artifactName: 'BlobArtifacts' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: Download PDB Artifacts - inputs: - artifactName: 'PDBArtifacts' - continueOnError: true - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }} \ No newline at end of file diff --git a/eng/common/templates/post-build/channels/netcore-tools-validation.yml b/eng/common/templates/post-build/channels/netcore-tools-validation.yml deleted file mode 100644 index d8447e49af6f..000000000000 --- a/eng/common/templates/post-build/channels/netcore-tools-validation.yml +++ /dev/null @@ -1,95 +0,0 @@ -parameters: - artifactsPublishingAdditionalParameters: '' - publishInstallersAndChecksums: false - -stages: -- stage: PVR_Publish - dependsOn: validate - variables: - - template: ../common-variables.yml - displayName: .NET Tools - Validation Publishing - jobs: - - template: ../setup-maestro-vars.yml - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - variables: - - group: DotNet-Blob-Feed - - group: AzureDevOps-Artifact-Feeds-Pats - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Validation_Channel_Id)) - pool: - vmImage: 'windows-2019' - steps: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: current - artifactName: PackageArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: current - artifactName: BlobArtifacts - - - task: DownloadBuildArtifacts@0 - displayName: Download Asset Manifests - inputs: - buildType: current - artifactName: AssetManifests - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:PublishToAzureDevOpsNuGetFeeds=true - /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/promote-build.yml - parameters: - ChannelId: ${{ variables.NetCore_Tools_Validation_Channel_Id }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index b4eed6f186c0..0a2c40c1035c 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,7 +1,9 @@ variables: - - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats + - group: DotNet-Blob-Feed - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage + - group: Publish-Build-Assets # .NET Core 3.1 Dev - name: PublicDevRelease_31_Channel_Id @@ -39,6 +41,14 @@ variables: - name: PublicRelease_31_Channel_Id value: 129 + # General Testing + - name: GeneralTesting_Channel_Id + value: 529 + + # .NET Core 3.1 Blazor Features + - name: NetCore_31_Blazor_Features_Channel_Id + value: 531 + # Whether the build is internal or not - name: IsInternalBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 7ee82d9ff183..ec80c65a923d 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -8,6 +8,7 @@ parameters: enable: false continueOnError: false params: '' + artifactNames: '' # These parameters let the user customize the call to sdk-task.ps1 for publishing # symbols & general artifacts as well as for signing validation @@ -94,54 +95,172 @@ stages: parameters: additionalParameters: ${{ parameters.SDLValidationParameters.params }} continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} + artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} -- template: \eng\common\templates\post-build\channels\netcore-dev-5.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Dev5_Publish' + channelName: '.NET Core 5 Dev' + channelId: 131 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-dev-31.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Dev31_Publish' + channelName: '.NET Core 3.1 Dev' + channelId: 128 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-tools-latest.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Tools_Latest_Publish' + channelName: '.NET Tools - Latest' + channelId: 2 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'PVR_Publish' + channelName: '.NET Tools - Validation' + channelId: 9 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-tools-validation.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Validation_Publish' + channelName: '.NET 3 Tools - Validation' + channelId: 390 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-3-tools-validation.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_3_Tools_Publish' + channelName: '.NET 3 Tools' + channelId: 344 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-3-tools.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release30_Publish' + channelName: '.NET Core 3.0 Release' + channelId: 19 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Release31_Publish' + channelName: '.NET Core 3.1 Release' + channelId: 129 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-release-30.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_Blazor31_Features_Publish' + channelName: '.NET Core 3.1 Blazor Features' + channelId: 531 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-blazor-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_30_Internal_Servicing_Publishing' + channelName: '.NET Core 3.0 Internal Servicing' + channelId: 184 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-release-31.yml +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NetCore_31_Internal_Servicing_Publishing' + channelName: '.NET Core 3.1 Internal Servicing' + channelId: 550 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'General_Testing_Publish' + channelName: 'General Testing' + channelId: 529 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing-symbols/nuget/v3/index.json' -- template: \eng\common\templates\post-build\channels\netcore-internal-30.yml +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_Tooling_Dev_Publishing' + channelName: '.NET Core Tooling Dev' + channelId: 548 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_Tooling_Release_Publishing' + channelName: '.NET Core Tooling Release' + channelId: 549 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' diff --git a/global.json b/global.json index 17454ad1bffa..5289c25502e2 100644 --- a/global.json +++ b/global.json @@ -25,7 +25,7 @@ }, "msbuild-sdks": { "Yarn.MSBuild": "1.15.2", - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19517.3", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19517.3" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19569.2", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19569.2" } } From d6c88a36ffe89614be26bf846d64791b9958406b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 22 Nov 2019 09:54:20 -0800 Subject: [PATCH 008/322] More cleaning up Blazor.Build package (#17157) * More cleaning up Blazor.Build package * Clean up MonoRuntime targets * Convert executables in to tasks * Add tests --- eng/Build.props | 1 + .../ResolveRuntimeDependenciesCommand.cs | 61 -- .../src/Cli/Commands/WriteBootJsonCommand.cs | 59 -- .../Blazor/Build/src/Cli/Program.cs | 33 - .../Blazor/Build/src/Core/BootJsonWriter.cs | 70 -- .../Microsoft.AspNetCore.Blazor.Build.csproj | 56 +- .../Microsoft.AspNetCore.Blazor.Build.nuspec | 4 +- .../src/ReferenceBlazorBuildFromSource.props | 25 + .../Build/src/ReferenceFromSource.props | 17 +- .../Build/src/Tasks/GenerateBlazorBootJson.cs | 74 ++ .../ResolveBlazorRuntimeDependencies.cs} | 38 +- .../Blazor/Build/src/targets/All.targets | 26 +- .../src/targets/Blazor.MonoRuntime.props | 20 +- .../src/targets/Blazor.MonoRuntime.targets | 627 +++--------- .../Blazor/Build/src/targets/Publish.targets | 5 +- .../Blazor/Build/test/BootJsonWriterTest.cs | 29 +- .../test/BuildIntegrationTests/Assert.cs | 950 ++++++++++++++++++ .../BuildIncrementalismTest.cs | 40 + .../BuildIntegrationTest.cs | 55 + .../BuildIntegrationTests/FileThumbPrint.cs | 74 ++ .../MSBuildProcessManager.cs | 282 ++++++ .../BuildIntegrationTests/MSBuildResult.cs | 28 + .../BuildIntegrationTests/ProjectDirectory.cs | 211 ++++ .../ProjectDirectoryTest.cs | 21 + .../PublishIntegrationTest.cs | 69 ++ ...osoft.AspNetCore.Blazor.Build.Tests.csproj | 25 +- .../test/RuntimeDependenciesResolverTest.cs | 4 +- .../Build/testassets/Directory.Build.props | 31 + .../Build/testassets/Directory.Build.targets | 2 + .../Build/testassets/standalone/App.razor | 8 + .../testassets/standalone/Pages/Index.razor | 5 + .../Build/testassets/standalone/Program.cs | 10 + .../testassets/standalone/_Imports.razor | 2 + .../testassets/standalone/standalone.csproj | 16 + .../testassets/standalone/wwwroot/index.html | 24 + src/Components/Web.JS/.gitignore | 1 - ...osoft.AspNetCore.Components.Web.JS.npmproj | 2 + .../Web.JS/dist/Release/blazor.server.js | 4 +- .../Web.JS/dist/Release/blazor.webassembly.js | 1 + 39 files changed, 2212 insertions(+), 798 deletions(-) delete mode 100644 src/Components/Blazor/Build/src/Cli/Commands/ResolveRuntimeDependenciesCommand.cs delete mode 100644 src/Components/Blazor/Build/src/Cli/Commands/WriteBootJsonCommand.cs delete mode 100644 src/Components/Blazor/Build/src/Cli/Program.cs delete mode 100644 src/Components/Blazor/Build/src/Core/BootJsonWriter.cs create mode 100644 src/Components/Blazor/Build/src/ReferenceBlazorBuildFromSource.props create mode 100644 src/Components/Blazor/Build/src/Tasks/GenerateBlazorBootJson.cs rename src/Components/Blazor/Build/src/{Core/RuntimeDependenciesResolver.cs => Tasks/ResolveBlazorRuntimeDependencies.cs} (86%) create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/Assert.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIncrementalismTest.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/FileThumbPrint.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildProcessManager.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildResult.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectory.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectoryTest.cs create mode 100644 src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs create mode 100644 src/Components/Blazor/Build/testassets/Directory.Build.props create mode 100644 src/Components/Blazor/Build/testassets/Directory.Build.targets create mode 100644 src/Components/Blazor/Build/testassets/standalone/App.razor create mode 100644 src/Components/Blazor/Build/testassets/standalone/Pages/Index.razor create mode 100644 src/Components/Blazor/Build/testassets/standalone/Program.cs create mode 100644 src/Components/Blazor/Build/testassets/standalone/_Imports.razor create mode 100644 src/Components/Blazor/Build/testassets/standalone/standalone.csproj create mode 100644 src/Components/Blazor/Build/testassets/standalone/wwwroot/index.html create mode 100644 src/Components/Web.JS/dist/Release/blazor.webassembly.js diff --git a/eng/Build.props b/eng/Build.props index 2a045abf95e4..f8a3b7027abf 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -34,6 +34,7 @@ $(RepoRoot)src\Installers\**\*.*proj; $(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj; $(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj; + $(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj; $(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj; $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj; $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj; diff --git a/src/Components/Blazor/Build/src/Cli/Commands/ResolveRuntimeDependenciesCommand.cs b/src/Components/Blazor/Build/src/Cli/Commands/ResolveRuntimeDependenciesCommand.cs deleted file mode 100644 index d5d37bb83390..000000000000 --- a/src/Components/Blazor/Build/src/Cli/Commands/ResolveRuntimeDependenciesCommand.cs +++ /dev/null @@ -1,61 +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 Microsoft.Extensions.CommandLineUtils; - -namespace Microsoft.AspNetCore.Blazor.Build.DevServer.Commands -{ - class ResolveRuntimeDependenciesCommand - { - public static void Command(CommandLineApplication command) - { - var referencesFile = command.Option("--references", - "The path to a file that lists the paths to given referenced dll files", - CommandOptionType.SingleValue); - - var baseClassLibrary = command.Option("--base-class-library", - "Full path to a directory in which BCL assemblies can be found", - CommandOptionType.MultipleValue); - - var outputPath = command.Option("--output", - "Path to the output file that will contain the list with the full paths of the resolved assemblies", - CommandOptionType.SingleValue); - - var mainAssemblyPath = command.Argument("assembly", - "Path to the assembly containing the entry point of the application."); - - command.OnExecute(() => - { - if (string.IsNullOrEmpty(mainAssemblyPath.Value) || - !baseClassLibrary.HasValue() || !outputPath.HasValue()) - { - command.ShowHelp(command.Name); - return 1; - } - - try - { - var referencesSources = referencesFile.HasValue() - ? File.ReadAllLines(referencesFile.Value()) - : Array.Empty(); - - RuntimeDependenciesResolver.ResolveRuntimeDependencies( - mainAssemblyPath.Value, - referencesSources, - baseClassLibrary.Values.ToArray(), - outputPath.Value()); - - return 0; - } - catch (Exception ex) - { - Console.WriteLine($"ERROR: {ex.Message}"); - Console.WriteLine(ex.StackTrace); - return 1; - } - }); - } - } -} diff --git a/src/Components/Blazor/Build/src/Cli/Commands/WriteBootJsonCommand.cs b/src/Components/Blazor/Build/src/Cli/Commands/WriteBootJsonCommand.cs deleted file mode 100644 index 6924bd525c96..000000000000 --- a/src/Components/Blazor/Build/src/Cli/Commands/WriteBootJsonCommand.cs +++ /dev/null @@ -1,59 +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.Extensions.CommandLineUtils; -using System; -using System.IO; - -namespace Microsoft.AspNetCore.Blazor.Build.DevServer.Commands -{ - internal class WriteBootJsonCommand - { - public static void Command(CommandLineApplication command) - { - var referencesFile = command.Option("--references", - "The path to a file that lists the paths to given referenced dll files", - CommandOptionType.SingleValue); - - var outputPath = command.Option("--output", - "Path to the output file", - CommandOptionType.SingleValue); - - var mainAssemblyPath = command.Argument("assembly", - "Path to the assembly containing the entry point of the application."); - - var linkerEnabledFlag = command.Option("--linker-enabled", - "If set, specifies that the application is being built with linking enabled.", - CommandOptionType.NoValue); - - command.OnExecute(() => - { - if (string.IsNullOrEmpty(mainAssemblyPath.Value) || !outputPath.HasValue()) - { - command.ShowHelp(command.Name); - return 1; - } - - try - { - var referencesSources = referencesFile.HasValue() - ? File.ReadAllLines(referencesFile.Value()) - : Array.Empty(); - - BootJsonWriter.WriteFile( - mainAssemblyPath.Value, - referencesSources, - linkerEnabledFlag.HasValue(), - outputPath.Value()); - return 0; - } - catch (Exception ex) - { - Console.WriteLine($"ERROR: {ex.Message}"); - Console.WriteLine(ex.StackTrace); - return 1; - } - }); - } - } -} diff --git a/src/Components/Blazor/Build/src/Cli/Program.cs b/src/Components/Blazor/Build/src/Cli/Program.cs deleted file mode 100644 index 3bd530453f8a..000000000000 --- a/src/Components/Blazor/Build/src/Cli/Program.cs +++ /dev/null @@ -1,33 +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.Blazor.Build.DevServer.Commands; -using Microsoft.Extensions.CommandLineUtils; - -namespace Microsoft.AspNetCore.Blazor.Build -{ - static class Program - { - static int Main(string[] args) - { - var app = new CommandLineApplication - { - Name = "Microsoft.AspNetCore.Blazor.Build" - }; - app.HelpOption("-?|-h|--help"); - - app.Command("resolve-dependencies", ResolveRuntimeDependenciesCommand.Command); - app.Command("write-boot-json", WriteBootJsonCommand.Command); - - if (args.Length > 0) - { - return app.Execute(args); - } - else - { - app.ShowHelp(); - return 0; - } - } - } -} diff --git a/src/Components/Blazor/Build/src/Core/BootJsonWriter.cs b/src/Components/Blazor/Build/src/Core/BootJsonWriter.cs deleted file mode 100644 index a98bbadb2068..000000000000 --- a/src/Components/Blazor/Build/src/Core/BootJsonWriter.cs +++ /dev/null @@ -1,70 +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.Text.Json; -using Microsoft.AspNetCore.Components; - -namespace Microsoft.AspNetCore.Blazor.Build -{ - internal class BootJsonWriter - { - public static void WriteFile( - string assemblyPath, - string[] assemblyReferences, - bool linkerEnabled, - string outputPath) - { - var bootJsonText = GetBootJsonContent( - AssemblyName.GetAssemblyName(assemblyPath).Name, - assemblyReferences, - linkerEnabled); - var normalizedOutputPath = Path.GetFullPath(outputPath); - Console.WriteLine("Writing boot data to: " + normalizedOutputPath); - File.WriteAllText(normalizedOutputPath, bootJsonText); - } - - public static string GetBootJsonContent(string entryAssembly, string[] assemblyReferences, bool linkerEnabled) - { - var data = new BootJsonData( - entryAssembly, - assemblyReferences, - linkerEnabled); - return JsonSerializer.Serialize(data, JsonSerializerOptionsProvider.Options); - } - - /// - /// Defines the structure of a Blazor boot JSON file - /// - readonly struct BootJsonData - { - /// - /// Gets the name of the assembly with the application entry point - /// - public string EntryAssembly { get; } - - /// - /// Gets the closure of assemblies to be loaded by Blazor WASM. This includes the application entry assembly. - /// - public IEnumerable Assemblies { get; } - - /// - /// Gets a value that determines if the linker is enabled. - /// - public bool LinkerEnabled { get; } - - public BootJsonData( - string entryAssembly, - IEnumerable assemblies, - bool linkerEnabled) - { - EntryAssembly = entryAssembly; - Assemblies = assemblies; - LinkerEnabled = linkerEnabled; - } - } - } -} diff --git a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj index f3f2e76131e2..daee88af6854 100644 --- a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj +++ b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj @@ -1,37 +1,71 @@ - + - $(DefaultNetCoreTargetFramework) + $(DefaultNetCoreTargetFramework);net46 + Microsoft.AspNetCore.Blazor.Build.Tasks + Microsoft.AspNetCore.Blazor.Build Build mechanism for ASP.NET Core Blazor applications. - Exe true false + false false - $(GenerateNuspecDependsOn);Publish true Microsoft.AspNetCore.Blazor.Build.nuspec - + - - - - + + + - - + + + + + + + + + <_NetCoreFilesToCopy Include="$(OutputPath)$(DefaultNetCoreTargetFramework)\*" TargetPath="netcoreapp\" /> + <_DesktopFilesToCopy Include="$(OutputPath)net46\*" TargetPath="netfx\" /> + <_AllFilesToCopy Include="@(_NetCoreFilesToCopy);@(_DesktopFilesToCopy)" /> + + + + + + + + + + diff --git a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec index 26ca818d7f60..b242d7cb1aa8 100644 --- a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec +++ b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec @@ -11,7 +11,7 @@ - - + + diff --git a/src/Components/Blazor/Build/src/ReferenceBlazorBuildFromSource.props b/src/Components/Blazor/Build/src/ReferenceBlazorBuildFromSource.props new file mode 100644 index 000000000000..0bcebe22fa12 --- /dev/null +++ b/src/Components/Blazor/Build/src/ReferenceBlazorBuildFromSource.props @@ -0,0 +1,25 @@ + + + + + $(MSBuildThisFileDirectory)..\..\..\ + $(ComponentsRoot)Web.JS\dist\$(Configuration)\blazor.webassembly.js + $(ComponentsRoot)Web.JS\dist\$(Configuration)\blazor.webassembly.js.map + $(MSBuildThisFileDirectory)bin\$(Configuration)\tools\ + + + + + + + + + + diff --git a/src/Components/Blazor/Build/src/ReferenceFromSource.props b/src/Components/Blazor/Build/src/ReferenceFromSource.props index 8067cdc131b9..884ddbad7a76 100644 --- a/src/Components/Blazor/Build/src/ReferenceFromSource.props +++ b/src/Components/Blazor/Build/src/ReferenceFromSource.props @@ -1,21 +1,6 @@ - - - - true - $(RepoRoot)src\Components\Web.JS\dist\$(Configuration)\blazor.*.js.* - - - - + true @@ -16,15 +18,25 @@ - + $(AssemblyName).blazor.config $(TargetDir)$(BlazorMetadataFileName) - - - - + + + <_BlazorConfigContent Include="$(MSBuildProjectFullPath)" /> + <_BlazorConfigContent Include="$(TargetPath)" /> + <_BlazorConfigContent Include="debug:true" Condition="'$(BlazorEnableDebugging)'=='true'" /> + + + + diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props index 03f70748ffb6..dc6926924bfe 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props @@ -1,22 +1,20 @@ - - $(MSBuildThisFileDirectory)../tools/blazor/blazor.*.js + + $(MSBuildThisFileDirectory)..\tools\blazor\blazor.webassembly.js none --disable-opt unreachablebodies --verbose --strip-security true --exclude-feature com --exclude-feature sre -v false -c link -u link -b true - dist/ - $(BaseBlazorDistPath)_content/ - $(BaseBlazorDistPath)_framework/ - $(BaseBlazorRuntimeOutputPath)_bin/ - $(BaseBlazorRuntimeOutputPath)wasm/ - $(BaseBlazorRuntimeOutputPath) - blazor/ - wwwroot/ + dist\ + $(BaseBlazorDistPath)_content\ + $(BaseBlazorDistPath)_framework\ + $(BaseBlazorRuntimeOutputPath)_bin\ + $(BaseBlazorRuntimeOutputPath)wasm\ + wwwroot\ blazor.boot.json - $(BaseBlazorRuntimeOutputPath)$(BlazorBootJsonName) + <_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 9b19e06bb5cf..26cd58d0c12c 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -1,206 +1,85 @@ + + true + + + + + $(MonoBaseClassLibraryPath) + $(MonoBaseClassLibraryFacadesPath) + $(MonoWasmRuntimePath) + $(MonoWasmFrameworkPath) + + + + + $(DotNetWebAssemblyArtifactsRoot)\wasm-bcl\wasm\ + $(DotNetWebAssemblyBCLPath)\Facades\ + $(DotNetWebAssemblyArtifactsRoot)\builds\debug\ + $(DotNetWebAssemblyArtifactsRoot)\framework\ + + Condition="'@(BlazorOutputWithTargetPath)' != '' and '$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'"> - + - - - - - - <_BlazorResolveReferencesDidRun>true - - - - - <_BlazorStatisticsOutput Include="@(BlazorItemOutput->'%(TargetOutputPath)')" /> + <_BlazorStatisticsOutput Include="@(BlazorOutputWithTargetPath->'%(TargetOutputPath)')" /> - - <_BlazorStatisticsReportImportance Condition="'$(BlazorOutputStatistics)' == ''">normal - <_BlazorStatisticsReportImportance Condition="'$(BlazorOutputStatistics)' != ''">high - - - + - - - - - _PrepareBlazorOutputConfiguration; - _DefineBlazorCommonInputs; - _BlazorResolveOutputBinaries; - _GenerateBlazorBootJson; - - - - - - - - - - - - <_BlazorShouldLinkApplicationAssemblies Condition="$(BlazorLinkOnBuild) == 'false'"> - <_BlazorShouldLinkApplicationAssemblies Condition="$(BlazorLinkOnBuild) == 'true'">true - <_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml - + - - - - - $(TargetDir)$(BaseBlazorRuntimeWasmOutputPath)%(FileName)%(Extension) - WebAssembly - true - - - $(TargetDir)$(BaseBlazorJsOutputPath)%(FileName)%(Extension) - BlazorRuntime - true - + + + + + + + $(BlazorRuntimeWasmOutputPath)%(FileName)%(Extension) + + + $(BaseBlazorRuntimeOutputPath)%(FileName)%(Extension) + - - <_BlazorPackageContentOutput Include="@(BlazorPackageContentFile)" Condition="%(SourcePackage) != ''"> - $(TargetDir)$(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension) - PreserveNewest + $(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension) - + + - - + + - $(IntermediateOutputPath)$(BaseBlazorIntermediateOutputPath) - $([MSBuild]::Escape($([System.IO.Path]::GetFullPath('$([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(BlazorIntermediateOutputPath)'))')))) - - - - - $(BlazorIntermediateOutputPath)inputs.basic.cache - - - $(BlazorIntermediateOutputPath)inputs.copylocal.txt - - - $(BlazorIntermediateOutputPath)inputs.linkerswitch.cache - - - - - $(BlazorIntermediateOutputPath)inputs.linker.cache + $(IntermediateOutputPath)blazor\ $(BlazorIntermediateOutputPath)linker.descriptor.xml @@ -208,151 +87,58 @@ $(BlazorIntermediateOutputPath)linker/ - - $(BlazorIntermediateOutputPath)linked.assemblies.txt - - - - - $(BlazorIntermediateOutputPath)resolvedassemblies/ - - - $(BlazorIntermediateOutputPath)resolved.assemblies.txt - - - - - $(BlazorIntermediateOutputPath) - - $(BlazorBootJsonIntermediateOutputDir)$(BlazorBootJsonName) - - - $(BlazorIntermediateOutputPath)inputs.bootjson.cache + $(BlazorIntermediateOutputPath)$(BlazorBootJsonName) - - $(BlazorIntermediateOutputPath)resolve-dependencies.txt + <_BlazorLinkerOutputCache>$(BlazorIntermediateOutputPath)linker.output - - $(BlazorIntermediateOutputPath)bootjson-references.txt - - - $(BlazorIntermediateOutputPath)embedded.resources.txt - - - - - $(TargetDir)$(BaseBlazorRuntimeBinOutputPath) + <_BlazorApplicationAssembliesCacheFile>$(BlazorIntermediateOutputPath)unlinked.output - - - - - - - - - - - - <_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" /> - - - <_BlazorCommonInput Include="@(IntermediateAssembly)" /> - <_BlazorCommonInput Include="@(_BlazorDependencyInput)" /> - <_BlazorCommonInput Include="$(_BlazorShouldLinkApplicationAssemblies)" /> - <_BlazorCommonInput Include="$(BlazorEnableDebugging)" /> - <_BlazorLinkingOption Condition="'$(_BlazorShouldLinkApplicationAssemblies)' == ''" Include="false" /> - <_BlazorLinkingOption Condition="'$(_BlazorShouldLinkApplicationAssemblies)' != ''" Include="true" /> - - - - - - - - - - - - - - - - - + <_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" /> + - + + + - - <_CollectLinkerOutputsDependsOn> - _GenerateLinkerDescriptor; - _CollectBlazorLinkerDescriptors; - _LinkBlazorApplication - - - - - - + Name="_ResolveBlazorOutputsWhenLinked" + Condition="'$(BlazorLinkOnBuild)' == 'true'" + DependsOnTargets="_GenerateLinkerDescriptor;_LinkBlazorApplication"> + + + + - + $(BlazorRuntimeBinOutputPath)%(FileName)%(Extension) - Assembly - true - - - $(BlazorRuntimeBinOutputPath)%(FileName)%(Extension) - Pdb - - + - + Condition="'@(BlazorLinkerDescriptor)' == ''"> + + <_PrepareLinkerDescriptorAssemblyLine Include="@(IntermediateAssembly->'%(FileName)')" /> @@ -367,60 +153,25 @@ Overwrite="true" WriteOnlyWhenDifferent="True" /> - - - - - - - - - - - <_BlazorLinkerInput Include="@(IntermediateAssembly)" /> - <_BlazorLinkerInput Include="@(_BlazorDependencyInput)" /> - <_BlazorLinkerInput Include="@(BlazorLinkerDescriptor)" /> - <_BlazorLinkerInput Include="$(AdditionalMonoLinkerOptions)" /> + - - - - - - - + + - - + @(BlazorLinkerDescriptor); + $(MSBuildAllProjects)" + Outputs="$(_BlazorLinkerOutputCache)"> + <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)"> $([System.String]::Copy('%(RelativeDir)').TrimEnd('\').TrimEnd('/')) @@ -428,9 +179,9 @@ - <_MonoBaseClassLibraryFolder Include="$(MonoBaseClassLibraryPath);$(MonoBaseClassLibraryFacadesPath);$(MonoWasmFrameworkPath)" /> + <_WebAssemblyBCLFolder Include="$(DotNetWebAssemblyBCLPath);$(DotNetWebAssemblyBCLFacadesPath);$(DotNetWebAssemblyFrameworkPath)" /> <_BlazorAssembliesToCopy Include="@(IntermediateAssembly->'-a "%(FullPath)"')" /> - <_BlazorFolderLookupPaths Include="@(_MonoBaseClassLibraryFolder->'-d "%(Identity)"')" /> + <_BlazorFolderLookupPaths Include="@(_WebAssemblyBCLFolder->'-d "%(Identity)"')" /> <_BlazorFolderLookupPaths Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" Include="@(_BlazorDependencyAssembly->'-d "%(RelativeDirNoTrailingSlash)"')" /> @@ -446,212 +197,92 @@ <_BlazorLinkerAdditionalOptions>-l $(MonoLinkerI18NAssemblies) $(AdditionalMonoLinkerOptions) - - + + + <_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> + + + - - <_BlazorLinkerOutput Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> - <_BlazorLinkerOutput Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" /> + <_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> - - - - - - - - - + - - - - <_CollectResolvedAssembliesDependsOn> - _ResolveBlazorApplicationAssemblies; - _ReadResolvedBlazorApplicationAssemblies; - _IntermediateCopyBlazorApplicationAssemblies; - _TouchBlazorApplicationAssemblies - - - + + Name="_ResolveBlazorOutputsWhenNotLinked" + DependsOnTargets="_ResolveBlazorRuntimeDependencies" + Condition="'$(BlazorLinkOnBuild)' != 'true'"> - + + + - + $(BlazorRuntimeBinOutputPath)%(FileName)%(Extension) - Assembly - true - - - $(BlazorRuntimeBinOutputPath)%(FileName)%(Extension) - Pdb - - + - - - <_ReferencesArg Condition="'@(_BlazorDependencyInput)' != ''">--references "$(BlazorResolveDependenciesFilePath)" - <_BclParameter>--base-class-library "$(MonoBaseClassLibraryPath)" --base-class-library "$(MonoBaseClassLibraryFacadesPath)" --base-class-library "$(MonoWasmFrameworkPath)" - - - - - - - - - - - - - - - - <_IntermediateResolvedRuntimeDependencies Include="@(_BlazorResolvedRuntimeDependencies->'$(BlazorIntermediateResolvedApplicationAssembliesOutputPath)%(FileName)%(Extension)')" /> - - - - - - - - - - - - - - - - + Outputs="$(_BlazorApplicationAssembliesCacheFile)"> - - - - - - - - - - - + <_WebAssemblyBCLFolder Include="$(DotNetWebAssemblyBCLPath);$(DotNetWebAssemblyBCLFacadesPath);$(DotNetWebAssemblyFrameworkPath)" /> + <_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" /> - + + + + - + - + + - <_AppReferences Include="@(BlazorItemOutput->WithMetadataValue('Type','Assembly')->'%(FileName)%(Extension)')" /> - <_AppReferences Include="@(BlazorItemOutput->WithMetadataValue('Type','Pdb')->'%(FileName)%(Extension)')" Condition="'$(BlazorEnableDebugging)' == 'true'" /> + <_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.dll'))" /> + <_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.pdb'))" Condition="'$(BlazorEnableDebugging)' == 'true'" /> - - <_LinkerEnabledFlag Condition="'$(_BlazorShouldLinkApplicationAssemblies)' != ''">--linker-enabled - <_ReferencesArg Condition="'@(_AppReferences)' != ''">--references "$(BlazorBootJsonReferencesFilePath)" - - - - - - - <_BlazorBootJson Include="$(BlazorBootJsonIntermediateOutputPath)" /> - <_BlazorBootJsonEmbeddedContentFile Include="$(BlazorBootJsonIntermediateOutputDir)_content\**\*.*" /> - - $(TargetDir)$(BlazorBootJsonOutputPath) - BootJson - - - $(TargetDir)dist/_content/%(RecursiveDir)%(FileName)%(Extension) - + + + + - - diff --git a/src/Components/Blazor/Build/src/targets/Publish.targets b/src/Components/Blazor/Build/src/targets/Publish.targets index e431ad1272cd..75c0ed5febc2 100644 --- a/src/Components/Blazor/Build/src/targets/Publish.targets +++ b/src/Components/Blazor/Build/src/targets/Publish.targets @@ -26,9 +26,8 @@ - <_BlazorGCTPDIDistFiles Include="@(BlazorItemOutput->'%(TargetOutputPath)')" /> - <_BlazorGCTPDI Include="@(_BlazorGCTPDIDistFiles)"> - $(BlazorPublishDistDir)$([MSBuild]::MakeRelative('$(TargetDir)dist\', %(Identity))) + <_BlazorGCTPDI Include="%(BlazorOutputWithTargetPath.Identity)"> + $(AssemblyName)\%(TargetOutputPath) diff --git a/src/Components/Blazor/Build/test/BootJsonWriterTest.cs b/src/Components/Blazor/Build/test/BootJsonWriterTest.cs index d917a40b06a8..1e2d89b573bb 100644 --- a/src/Components/Blazor/Build/test/BootJsonWriterTest.cs +++ b/src/Components/Blazor/Build/test/BootJsonWriterTest.cs @@ -1,28 +1,41 @@ // 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 Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; using Xunit; -namespace Microsoft.AspNetCore.Blazor.Build.Test +namespace Microsoft.AspNetCore.Blazor.Build { public class BootJsonWriterTest { [Fact] - public void ProducesJsonReferencingAssemblyAndDependencies() + public async Task ProducesJsonReferencingAssemblyAndDependencies() { // Arrange/Act var assemblyReferences = new string[] { "MyApp.EntryPoint.dll", "System.Abc.dll", "MyApp.ClassLib.dll", }; - var content = BootJsonWriter.GetBootJsonContent( + using var stream = new MemoryStream(); + + // Act + GenerateBlazorBootJson.WriteBootJson( + stream, "MyApp.Entrypoint.dll", assemblyReferences, linkerEnabled: true); // Assert - var parsedContent = JsonConvert.DeserializeObject(content); - Assert.Equal("MyApp.Entrypoint.dll", parsedContent["entryAssembly"].Value()); - Assert.Equal(assemblyReferences, parsedContent["assemblies"].Values()); + stream.Position = 0; + using var parsedContent = await JsonDocument.ParseAsync(stream); + var rootElement = parsedContent.RootElement; + Assert.Equal("MyApp.Entrypoint.dll", rootElement.GetProperty("entryAssembly").GetString()); + var assembliesElement = rootElement.GetProperty("assemblies"); + Assert.Equal(assemblyReferences.Length, assembliesElement.GetArrayLength()); + for (var i = 0; i < assemblyReferences.Length; i++) + { + Assert.Equal(assemblyReferences[i], assembliesElement[i].GetString()); + } + Assert.True(rootElement.GetProperty("linkerEnabled").GetBoolean()); } } } diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/Assert.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/Assert.cs new file mode 100644 index 000000000000..8d0aa4b6dab1 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/Assert.cs @@ -0,0 +1,950 @@ +// 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.IO.Compression; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; +using System.Text.RegularExpressions; + +namespace Microsoft.AspNetCore.Blazor.Build +{ + internal class Assert : Xunit.Assert + { + // Matches `{filename}: error {code}: {message} [{project}] + // See https://stackoverflow.com/questions/3441452/msbuild-and-ignorestandarderrorwarningformat/5180353#5180353 + private static readonly Regex ErrorRegex = new Regex(@"^(?'location'.+): error (?'errorcode'[A-Z0-9]+): (?'message'.+) \[(?'project'.+)\]$"); + private static readonly Regex WarningRegex = new Regex(@"^(?'location'.+): warning (?'errorcode'[A-Z0-9]+): (?'message'.+) \[(?'project'.+)\]$"); + private static readonly string[] AllowedBuildWarnings = new[] + { + "MSB3491" , // The process cannot access the file. As long as the build succeeds, we're ok. + "NETSDK1071", // "A PackageReference to 'Microsoft.NETCore.App' specified a Version ..." + }; + + public static void BuildPassed(MSBuildResult result, bool allowWarnings = false) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (result.ExitCode != 0) + { + throw new BuildFailedException(result); + } + + var buildWarnings = GetBuildWarnings(result) + .Where(m => !AllowedBuildWarnings.Contains(m.match.Groups["errorcode"].Value)) + .Select(m => m.line); + + if (!allowWarnings && buildWarnings.Any()) + { + throw new BuildWarningsException(result, buildWarnings); + } + } + + public static void BuildError(MSBuildResult result, string errorCode, string location = null) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + // We don't really need to search line by line, I'm doing this so that it's possible/easy to debug. + var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i]; + var match = ErrorRegex.Match(line); + if (match.Success) + { + if (match.Groups["errorcode"].Value != errorCode) + { + continue; + } + + if (location != null && match.Groups["location"].Value.Trim() != location) + { + continue; + } + + // This is a match + return; + } + } + + throw new BuildErrorMissingException(result, errorCode, location); + } + + public static void BuildWarning(MSBuildResult result, string errorCode, string location = null) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + // We don't really need to search line by line, I'm doing this so that it's possible/easy to debug. + foreach (var (_, match) in GetBuildWarnings(result)) + { + if (match.Groups["errorcode"].Value != errorCode) + { + continue; + } + + if (location != null && match.Groups["location"].Value.Trim() != location) + { + continue; + } + + // This is a match + return; + } + + throw new BuildErrorMissingException(result, errorCode, location); + } + + private static IEnumerable<(string line, Match match)> GetBuildWarnings(MSBuildResult result) + { + var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i]; + var match = WarningRegex.Match(line); + if (match.Success) + { + yield return (line, match); + } + } + } + + public static void BuildFailed(MSBuildResult result) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + }; + + if (result.ExitCode == 0) + { + throw new BuildPassedException(result); + } + } + + public static void BuildOutputContainsLine(MSBuildResult result, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (match == null) + { + throw new ArgumentNullException(nameof(match)); + } + + // We don't really need to search line by line, I'm doing this so that it's possible/easy to debug. + var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i].Trim(); + if (line == match) + { + return; + } + } + + throw new BuildOutputMissingException(result, match); + } + + public static void BuildOutputDoesNotContainLine(MSBuildResult result, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (match == null) + { + throw new ArgumentNullException(nameof(match)); + } + + // We don't really need to search line by line, I'm doing this so that it's possible/easy to debug. + var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i].Trim(); + if (line == match) + { + throw new BuildOutputContainsLineException(result, match); + } + } + } + + public static void FileContains(MSBuildResult result, string filePath, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var text = File.ReadAllText(filePath); + if (text.Contains(match)) + { + return; + } + + throw new FileContentMissingException(result, filePath, File.ReadAllText(filePath), match); + } + + public static void FileDoesNotContain(MSBuildResult result, string filePath, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var text = File.ReadAllText(filePath); + if (text.Contains(match)) + { + throw new FileContentFoundException(result, filePath, File.ReadAllText(filePath), match); + } + } + + public static void FileContentEquals(MSBuildResult result, string filePath, string expected) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var actual = File.ReadAllText(filePath); + if (!actual.Equals(expected, StringComparison.Ordinal)) + { + throw new FileContentNotEqualException(result, filePath, expected, actual); + } + } + + public static void FileEquals(MSBuildResult result, string expected, string actual) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + expected = Path.Combine(result.Project.DirectoryPath, expected); + actual = Path.Combine(result.Project.DirectoryPath, actual); + FileExists(result, expected); + FileExists(result, actual); + + if (!Enumerable.SequenceEqual(File.ReadAllBytes(expected), File.ReadAllBytes(actual))) + { + throw new FilesNotEqualException(result, expected, actual); + } + } + + public static void FileContainsLine(MSBuildResult result, string filePath, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var lines = File.ReadAllLines(filePath); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i].Trim(); + if (line == match) + { + return; + } + } + + throw new FileContentMissingException(result, filePath, File.ReadAllText(filePath), match); + } + + public static void FileDoesNotContainLine(MSBuildResult result, string filePath, string match) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var lines = File.ReadAllLines(filePath); + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i].Trim(); + if (line == match) + { + throw new FileContentFoundException(result, filePath, File.ReadAllText(filePath), match); + } + } + } + + public static string FileExists(MSBuildResult result, params string[] paths) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var filePath = Path.Combine(result.Project.DirectoryPath, Path.Combine(paths)); + if (!File.Exists(filePath)) + { + throw new FileMissingException(result, filePath); + } + + return filePath; + } + + public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (directoryPath == null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + if (searchPattern == null) + { + throw new ArgumentNullException(nameof(searchPattern)); + } + + directoryPath = Path.Combine(result.Project.DirectoryPath, directoryPath); + + if (Directory.Exists(directoryPath)) + { + var files = Directory.GetFiles(directoryPath, searchPattern, SearchOption.AllDirectories); + if (files.Length != expected) + { + throw new FileCountException(result, expected, directoryPath, searchPattern, files); + } + } + else if (expected > 0) + { + // directory doesn't exist, that's OK if we expected to find nothing. + throw new FileCountException(result, expected, directoryPath, searchPattern, Array.Empty()); + } + } + + public static void FileDoesNotExist(MSBuildResult result, params string[] paths) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var filePath = Path.Combine(result.Project.DirectoryPath, Path.Combine(paths)); + if (File.Exists(filePath)) + { + throw new FileFoundException(result, filePath); + } + } + + public static void NuspecContains(MSBuildResult result, string nuspecPath, string expected) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (nuspecPath == null) + { + throw new ArgumentNullException(nameof(nuspecPath)); + } + + if (expected == null) + { + throw new ArgumentNullException(nameof(expected)); + } + + nuspecPath = Path.Combine(result.Project.DirectoryPath, nuspecPath); + FileExists(result, nuspecPath); + + var content = File.ReadAllText(nuspecPath); + if (!content.Contains(expected)) + { + throw new NuspecException(result, nuspecPath, content, expected); + } + } + + public static void NuspecDoesNotContain(MSBuildResult result, string nuspecPath, string expected) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (nuspecPath == null) + { + throw new ArgumentNullException(nameof(nuspecPath)); + } + + if (expected == null) + { + throw new ArgumentNullException(nameof(expected)); + } + + nuspecPath = Path.Combine(result.Project.DirectoryPath, nuspecPath); + FileExists(result, nuspecPath); + + var content = File.ReadAllText(nuspecPath); + if (content.Contains(expected)) + { + throw new NuspecFoundException(result, nuspecPath, content, expected); + } + } + + // This method extracts the nupkg to a fixed directory path. To avoid the extra work of + // cleaning up after each invocation, this method accepts multiple files. + public static void NupkgContains(MSBuildResult result, string nupkgPath, params string[] filePaths) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (nupkgPath == null) + { + throw new ArgumentNullException(nameof(nupkgPath)); + } + + if (filePaths == null) + { + throw new ArgumentNullException(nameof(filePaths)); + } + + nupkgPath = Path.Combine(result.Project.DirectoryPath, nupkgPath); + FileExists(result, nupkgPath); + + var unzipped = Path.Combine(result.Project.DirectoryPath, Path.GetFileNameWithoutExtension(nupkgPath)); + ZipFile.ExtractToDirectory(nupkgPath, unzipped); + + foreach (var filePath in filePaths) + { + if (!File.Exists(Path.Combine(unzipped, filePath))) + { + throw new NupkgFileMissingException(result, nupkgPath, filePath); + } + } + } + + // This method extracts the nupkg to a fixed directory path. To avoid the extra work of + // cleaning up after each invocation, this method accepts multiple files. + public static void NupkgDoesNotContain(MSBuildResult result, string nupkgPath, params string[] filePaths) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + if (nupkgPath == null) + { + throw new ArgumentNullException(nameof(nupkgPath)); + } + + if (filePaths == null) + { + throw new ArgumentNullException(nameof(filePaths)); + } + + nupkgPath = Path.Combine(result.Project.DirectoryPath, nupkgPath); + FileExists(result, nupkgPath); + + var unzipped = Path.Combine(result.Project.DirectoryPath, Path.GetFileNameWithoutExtension(nupkgPath)); + ZipFile.ExtractToDirectory(nupkgPath, unzipped); + + foreach (var filePath in filePaths) + { + if (File.Exists(Path.Combine(unzipped, filePath))) + { + throw new NupkgFileFoundException(result, nupkgPath, filePath); + } + } + } + + public static void AssemblyContainsType(MSBuildResult result, string assemblyPath, string fullTypeName) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath)); + + var typeNames = GetDeclaredTypeNames(assemblyPath); + Assert.Contains(fullTypeName, typeNames); + } + + public static void AssemblyDoesNotContainType(MSBuildResult result, string assemblyPath, string fullTypeName) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath)); + + var typeNames = GetDeclaredTypeNames(assemblyPath); + Assert.DoesNotContain(fullTypeName, typeNames); + } + + private static IEnumerable GetDeclaredTypeNames(string assemblyPath) + { + using (var file = File.OpenRead(assemblyPath)) + { + var peReader = new PEReader(file); + var metadataReader = peReader.GetMetadataReader(); + return metadataReader.TypeDefinitions.Where(t => !t.IsNil).Select(t => + { + var type = metadataReader.GetTypeDefinition(t); + return metadataReader.GetString(type.Namespace) + "." + metadataReader.GetString(type.Name); + }).ToArray(); + } + } + + public static void AssemblyHasAttribute(MSBuildResult result, string assemblyPath, string fullTypeName) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath)); + + var typeNames = GetAssemblyAttributes(assemblyPath); + Assert.Contains(fullTypeName, typeNames); + } + + private static IEnumerable GetAssemblyAttributes(string assemblyPath) + { + using (var file = File.OpenRead(assemblyPath)) + { + var peReader = new PEReader(file); + var metadataReader = peReader.GetMetadataReader(); + return metadataReader.CustomAttributes.Where(t => !t.IsNil).Select(t => + { + var attribute = metadataReader.GetCustomAttribute(t); + var constructor = metadataReader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); + var type = metadataReader.GetTypeReference((TypeReferenceHandle)constructor.Parent); + + return metadataReader.GetString(type.Namespace) + "." + metadataReader.GetString(type.Name); + }).ToArray(); + } + } + + private abstract class MSBuildXunitException : Xunit.Sdk.XunitException + { + protected MSBuildXunitException(MSBuildResult result) + { + Result = result; + } + + protected abstract string Heading { get; } + + public MSBuildResult Result { get; } + + public override string Message + { + get + { + var message = new StringBuilder(); + message.AppendLine(Heading); + message.Append(Result.FileName); + message.Append(" "); + message.Append(Result.Arguments); + message.AppendLine(); + message.AppendLine(); + message.Append(Result.Output); + message.AppendLine(); + message.Append("Exit Code:"); + message.Append(Result.ExitCode); + return message.ToString(); + } + } + } + + private class BuildErrorMissingException : MSBuildXunitException + { + public BuildErrorMissingException(MSBuildResult result, string errorCode, string location) + : base(result) + { + ErrorCode = errorCode; + Location = location; + } + + public string ErrorCode { get; } + + public string Location { get; } + + protected override string Heading + { + get + { + return + $"Error code '{ErrorCode}' was not found." + Environment.NewLine + + $"Looking for '{Location ?? ".*"}: error {ErrorCode}: .*'"; + } + } + } + + private class BuildFailedException : MSBuildXunitException + { + public BuildFailedException(MSBuildResult result) + : base(result) + { + } + + protected override string Heading => "Build failed."; + } + + private class BuildWarningsException : MSBuildXunitException + { + public BuildWarningsException(MSBuildResult result, IEnumerable warnings) + : base(result) + { + Warnings = warnings.ToList(); + } + + public List Warnings { get; } + + protected override string Heading => "Build contains unexpected warnings: " + string.Join(Environment.NewLine, Warnings); + } + + private class BuildPassedException : MSBuildXunitException + { + public BuildPassedException(MSBuildResult result) + : base(result) + { + } + + protected override string Heading => "Build should have failed, but it passed."; + } + + private class BuildOutputMissingException : MSBuildXunitException + { + public BuildOutputMissingException(MSBuildResult result, string match) + : base(result) + { + Match = match; + } + + public string Match { get; } + + protected override string Heading => $"Build did not contain the line: '{Match}'."; + } + + private class BuildOutputContainsLineException : MSBuildXunitException + { + public BuildOutputContainsLineException(MSBuildResult result, string match) + : base(result) + { + Match = match; + } + + public string Match { get; } + + protected override string Heading => $"Build output contains the line: '{Match}'."; + } + + private class FileContentFoundException : MSBuildXunitException + { + public FileContentFoundException(MSBuildResult result, string filePath, string content, string match) + : base(result) + { + FilePath = filePath; + Content = content; + Match = match; + } + + public string Content { get; } + + public string FilePath { get; } + + public string Match { get; } + + protected override string Heading + { + get + { + var builder = new StringBuilder(); + builder.AppendFormat("File content of '{0}' should not contain line: '{1}'.", FilePath, Match); + builder.AppendLine(); + builder.AppendLine(); + builder.AppendLine(Content); + return builder.ToString(); + } + } + } + + private class FileContentMissingException : MSBuildXunitException + { + public FileContentMissingException(MSBuildResult result, string filePath, string content, string match) + : base(result) + { + FilePath = filePath; + Content = content; + Match = match; + } + + public string Content { get; } + + public string FilePath { get; } + + public string Match { get; } + + protected override string Heading + { + get + { + var builder = new StringBuilder(); + builder.AppendFormat("File content of '{0}' did not contain the line: '{1}'.", FilePath, Match); + builder.AppendLine(); + builder.AppendLine(); + builder.AppendLine(Content); + return builder.ToString(); + } + } + } + + private class FileContentNotEqualException : MSBuildXunitException + { + public FileContentNotEqualException(MSBuildResult result, string filePath, string expected, string actual) + : base(result) + { + FilePath = filePath; + Expected = expected; + Actual = actual; + } + + public string Actual { get; } + + public string FilePath { get; } + + public string Expected { get; } + + protected override string Heading + { + get + { + var builder = new StringBuilder(); + builder.AppendFormat("File content of '{0}' did not match the expected content: '{1}'.", FilePath, Expected); + builder.AppendLine(); + builder.AppendLine(); + builder.AppendLine(Actual); + return builder.ToString(); + } + } + } + + private class FilesNotEqualException : MSBuildXunitException + { + public FilesNotEqualException(MSBuildResult result, string expected, string actual) + : base(result) + { + Expected = expected; + Actual = actual; + } + + public string Actual { get; } + + public string Expected { get; } + + protected override string Heading + { + get + { + var builder = new StringBuilder(); + builder.AppendFormat("File content of '{0}' did not match the contents of '{1}'.", Expected, Actual); + builder.AppendLine(); + builder.AppendLine(); + builder.AppendLine(Actual); + return builder.ToString(); + } + } + } + + private class FileMissingException : MSBuildXunitException + { + public FileMissingException(MSBuildResult result, string filePath) + : base(result) + { + FilePath = filePath; + } + + public string FilePath { get; } + + protected override string Heading => $"File: '{FilePath}' was not found."; + } + + private class FileCountException : MSBuildXunitException + { + public FileCountException(MSBuildResult result, int expected, string directoryPath, string searchPattern, string[] files) + : base(result) + { + Expected = expected; + DirectoryPath = directoryPath; + SearchPattern = searchPattern; + Files = files; + } + + public string DirectoryPath { get; } + + public int Expected { get; } + + public string[] Files { get; } + + public string SearchPattern { get; } + + protected override string Heading + { + get + { + var heading = new StringBuilder(); + heading.AppendLine($"Expected {Expected} files matching {SearchPattern} in {DirectoryPath}, found {Files.Length}."); + + if (Files.Length > 0) + { + heading.AppendLine("Files:"); + + foreach (var file in Files) + { + heading.Append("\t"); + heading.Append(file); + } + + heading.AppendLine(); + } + + return heading.ToString(); + } + } + } + + private class FileFoundException : MSBuildXunitException + { + public FileFoundException(MSBuildResult result, string filePath) + : base(result) + { + FilePath = filePath; + } + + public string FilePath { get; } + + protected override string Heading => $"File: '{FilePath}' was found, but should not exist."; + } + + private class NuspecException : MSBuildXunitException + { + public NuspecException(MSBuildResult result, string filePath, string content, string expected) + : base(result) + { + FilePath = filePath; + Content = content; + Expected = expected; + } + + public string Content { get; } + + public string Expected { get; } + + public string FilePath { get; } + + protected override string Heading + { + get + { + return + $"nuspec: '{FilePath}' did not contain the expected content." + Environment.NewLine + + Environment.NewLine + + $"expected: {Expected}" + Environment.NewLine + + Environment.NewLine + + $"actual: {Content}"; + } + } + } + + private class NuspecFoundException : MSBuildXunitException + { + public NuspecFoundException(MSBuildResult result, string filePath, string content, string expected) + : base(result) + { + FilePath = filePath; + Content = content; + Expected = expected; + } + + public string Content { get; } + + public string Expected { get; } + + public string FilePath { get; } + + protected override string Heading + { + get + { + return + $"nuspec: '{FilePath}' should not contain the content {Expected}." + + Environment.NewLine + + $"actual content: {Content}"; + } + } + } + + private class NupkgFileMissingException : MSBuildXunitException + { + public NupkgFileMissingException(MSBuildResult result, string nupkgPath, string filePath) + : base(result) + { + NupkgPath = nupkgPath; + FilePath = filePath; + } + + public string FilePath { get; } + + public string NupkgPath { get; } + + protected override string Heading => $"File: '{FilePath}' was not found was not found in {NupkgPath}."; + } + + private class NupkgFileFoundException : MSBuildXunitException + { + public NupkgFileFoundException(MSBuildResult result, string nupkgPath, string filePath) + : base(result) + { + NupkgPath = nupkgPath; + FilePath = filePath; + } + + public string FilePath { get; } + + public string NupkgPath { get; } + + protected override string Heading => $"File: '{FilePath}' was found in {NupkgPath}."; + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIncrementalismTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIncrementalismTest.cs new file mode 100644 index 000000000000..73d864502989 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIncrementalismTest.cs @@ -0,0 +1,40 @@ +// 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.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Build +{ + public class BuildIncrementalismTest + { + [Fact] + public async Task Build_WithLinker_IsIncremental() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + var result = await MSBuildProcessManager.DotnetMSBuild(project); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + + // Act + var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, project.BuildOutputDirectory); + + // Assert + for (var i = 0; i < 3; i++) + { + result = await MSBuildProcessManager.DotnetMSBuild(project); + Assert.BuildPassed(result); + + var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, project.BuildOutputDirectory); + Assert.Equal(thumbPrint.Count, newThumbPrint.Count); + for (var j = 0; j < thumbPrint.Count; j++) + { + Assert.Equal(thumbPrint[j], newThumbPrint[j]); + } + } + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs new file mode 100644 index 000000000000..ddd7fcb43bd2 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs @@ -0,0 +1,55 @@ +// 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.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Build +{ + public class BuildIntegrationTest + { + [Fact] + public async Task Build_WithDefaultSettings_Works() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + var result = await MSBuildProcessManager.DotnetMSBuild(project); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + } + + [Fact] + public async Task Build_WithLinkOnBuildDisabled_Works() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + project.AddProjectFileContent( +@" + false +"); + + var result = await MSBuildProcessManager.DotnetMSBuild(project); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/FileThumbPrint.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/FileThumbPrint.cs new file mode 100644 index 000000000000..58b5499e8bc6 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/FileThumbPrint.cs @@ -0,0 +1,74 @@ +// 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.Blazor.Build +{ + internal class FileThumbPrint : IEquatable + { + 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}"; + } + + /// + /// Returns a list of thumbprints for all files (recursive) in the specified directory, sorted by file paths. + /// + public static List 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(); + foreach (var file in files) + { + var thumbprint = Create(file); + thumbprintLookup.Add(thumbprint); + } + + thumbprintLookup.Sort(Comparer.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(); + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildProcessManager.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildProcessManager.cs new file mode 100644 index 000000000000..b7e16ca07291 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildProcessManager.cs @@ -0,0 +1,282 @@ +// 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.Blazor.Build +{ + internal static class MSBuildProcessManager + { + public static Task DotnetMSBuild( + ProjectDirectory project, + string target = "Build", + string args = null) + { + var buildArgumentList = new List + { + // 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(args); + + var buildArguments = string.Join(" ", buildArgumentList); + + return MSBuildProcessManager.RunProcessAsync(project, buildArguments); + } + + public static async Task 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"; + + var processResult = await RunProcessCoreAsync(processStartInfo, timeout); + + return new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output); + } + + internal static Task 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(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 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 CaptureDump(Process process, TimeSpan? timeout, StringBuilder diagnostics) + { + var metadataAttributes = Assembly.GetExecutingAssembly() + .GetCustomAttributes(); + + 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(); + + 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; } + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildResult.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildResult.cs new file mode 100644 index 000000000000..9a83df922b01 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/MSBuildResult.cs @@ -0,0 +1,28 @@ +// 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.Blazor.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; } + } + +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectory.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectory.cs new file mode 100644 index 000000000000..e50b750ae491 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectory.cs @@ -0,0 +1,211 @@ +// 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.Blazor.Build +{ + internal class ProjectDirectory : IDisposable + { + public bool PreserveWorkingDirectory { get; set; } = false; + + 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", "Blazor", "Build", "testassets"); + foreach (var project in new string[] { projectName, }.Concat(additionalProjects ?? Array.Empty())) + { + 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 beforeDirectoryPropsContent = +$@" + + {repoRoot} + +"; + File.WriteAllText(Path.Combine(projectDestination, "Before.Directory.Build.props"), beforeDirectoryPropsContent); + + new List { "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"; + +#if DEBUG + public string Configuration => "Debug"; +#elif RELEASE + public string Configuration => "Release"; +#else +#error Configuration not supported +#endif + + 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("", content); + File.WriteAllText(ProjectFilePath, 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() + .FirstOrDefault(f => f.Key == key) + ?.Value; + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectoryTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectoryTest.cs new file mode 100644 index 000000000000..23badb4296f8 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/ProjectDirectoryTest.cs @@ -0,0 +1,21 @@ +// 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.Blazor.Build +{ + public class ProjectDirectoryTest + { + [Fact] + public void ProjectDirectory_IsNotSetToBePreserved() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + + // Act & Assert + // This flag is only meant for local debugging and should not be set when checking in. + Assert.False(project.PreserveWorkingDirectory); + } + } +} diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs new file mode 100644 index 000000000000..606fb88abae6 --- /dev/null +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -0,0 +1,69 @@ +// 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.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Build +{ + public class PublishIntegrationTest + { + [Fact] + public async Task Publish_WithDefaultSettings_Works() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath)); + + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify web.config + Assert.FileExists(result, publishDirectory, "web.config"); + } + + [Fact] + public async Task Publish_WithLinkOnBuildDisabled_Works() + { + // Arrange + using var project = ProjectDirectory.Create("standalone"); + project.AddProjectFileContent( +@" + false +"); + + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath)); + + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify web.config + Assert.FileExists(result, publishDirectory, "web.config"); + } + } +} diff --git a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj index 0dc2bf45eb63..5b7c3827cad4 100644 --- a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj +++ b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj @@ -25,16 +25,39 @@ + + + - + + + <_Parameter1>Testing.RepoRoot + <_Parameter2>$(RepoRoot) + + + + + + <_TestAsset Include="..\testassets\standalone\standalone.csproj" /> + + + + + diff --git a/src/Components/Blazor/Build/test/RuntimeDependenciesResolverTest.cs b/src/Components/Blazor/Build/test/RuntimeDependenciesResolverTest.cs index 5838d419d7aa..951b1a61df6c 100644 --- a/src/Components/Blazor/Build/test/RuntimeDependenciesResolverTest.cs +++ b/src/Components/Blazor/Build/test/RuntimeDependenciesResolverTest.cs @@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Testing; using Xunit; -namespace Microsoft.AspNetCore.Blazor.Build.Test +namespace Microsoft.AspNetCore.Blazor.Build { public class RuntimeDependenciesResolverTest { @@ -109,7 +109,7 @@ uncalled implementation code from mscorlib.dll anyway. // Act - var paths = RuntimeDependenciesResolver + var paths = ResolveBlazorRuntimeDependencies .ResolveRuntimeDependenciesCore( mainAssemblyLocation, references, diff --git a/src/Components/Blazor/Build/testassets/Directory.Build.props b/src/Components/Blazor/Build/testassets/Directory.Build.props new file mode 100644 index 000000000000..cf4b11d0cf45 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/Directory.Build.props @@ -0,0 +1,31 @@ + + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\ + $(RepoRoot)src\Components\ + $(ComponentsRoot)Blazor\Build\src\ + $(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props + + + netcoreapp3.1 + + false + false + + + + + + + + + + + diff --git a/src/Components/Blazor/Build/testassets/Directory.Build.targets b/src/Components/Blazor/Build/testassets/Directory.Build.targets new file mode 100644 index 000000000000..8c119d5413b5 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/src/Components/Blazor/Build/testassets/standalone/App.razor b/src/Components/Blazor/Build/testassets/standalone/App.razor new file mode 100644 index 000000000000..eba23da9b5ae --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/App.razor @@ -0,0 +1,8 @@ + + + + + +

Sorry, there's nothing at this address.

+
+
diff --git a/src/Components/Blazor/Build/testassets/standalone/Pages/Index.razor b/src/Components/Blazor/Build/testassets/standalone/Pages/Index.razor new file mode 100644 index 000000000000..16dac3192520 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/Pages/Index.razor @@ -0,0 +1,5 @@ +@page "/" + +

Hello, world!

+ +Welcome to your new app. diff --git a/src/Components/Blazor/Build/testassets/standalone/Program.cs b/src/Components/Blazor/Build/testassets/standalone/Program.cs new file mode 100644 index 000000000000..16bfae7e439c --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/Program.cs @@ -0,0 +1,10 @@ + +namespace standalone +{ + public class Program + { + public static void Main(string[] args) + { + } + } +} diff --git a/src/Components/Blazor/Build/testassets/standalone/_Imports.razor b/src/Components/Blazor/Build/testassets/standalone/_Imports.razor new file mode 100644 index 000000000000..129b440e8600 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/_Imports.razor @@ -0,0 +1,2 @@ +@using Microsoft.AspNetCore.Components.Routing +@using standalone diff --git a/src/Components/Blazor/Build/testassets/standalone/standalone.csproj b/src/Components/Blazor/Build/testassets/standalone/standalone.csproj new file mode 100644 index 000000000000..60302d4a0c40 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/standalone.csproj @@ -0,0 +1,16 @@ + + + + + netstandard2.1 + 3.0 + + + + + + + + + + diff --git a/src/Components/Blazor/Build/testassets/standalone/wwwroot/index.html b/src/Components/Blazor/Build/testassets/standalone/wwwroot/index.html new file mode 100644 index 000000000000..85994d6e89fe --- /dev/null +++ b/src/Components/Blazor/Build/testassets/standalone/wwwroot/index.html @@ -0,0 +1,24 @@ + + + + + + + standalone + + + + + + + Loading... + +
+ An unhandled error has occurred. + Reload + 🗙 +
+ + + + diff --git a/src/Components/Web.JS/.gitignore b/src/Components/Web.JS/.gitignore index 6adb60389081..10999e07926c 100644 --- a/src/Components/Web.JS/.gitignore +++ b/src/Components/Web.JS/.gitignore @@ -1,3 +1,2 @@ node_modules/ dist/Debug/ -dist/Release/blazor.webassembly.js \ No newline at end of file diff --git a/src/Components/Web.JS/Microsoft.AspNetCore.Components.Web.JS.npmproj b/src/Components/Web.JS/Microsoft.AspNetCore.Components.Web.JS.npmproj index 8e0a17ece09e..4e64a10edbba 100644 --- a/src/Components/Web.JS/Microsoft.AspNetCore.Components.Web.JS.npmproj +++ b/src/Components/Web.JS/Microsoft.AspNetCore.Components.Web.JS.npmproj @@ -21,6 +21,8 @@ Private="false" />
+ + diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index 77a2e1948d4b..e3ada49ef785 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -5,11 +5,11 @@ * @author Feross Aboukhadijeh * @license MIT */ -var r=n(50),o=n(51),i=n(52);function a(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,c=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,c/=2,n/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;is&&(n=s-c),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function _(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function I(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:u>223?3:u>191?2:1;if(o+f<=n)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(i=e[o+1]))&&(c=(31&u)<<6|63&i)>127&&(l=c);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(c=(15&u)<<12|(63&i)<<6|63&a)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(c=(15&u)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return x(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return _(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},c.prototype.equals=function(e){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===c.compare(this,e)},c.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},c.prototype.compare=function(e,t,n,r,o){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),u=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function O(e,t,n,r,o,i){if(!c.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function M(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function A(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||A(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function j(e,t,n,r,i){return i||A(e,0,n,8),o.write(e,t,n,r,52,8),n+8}c.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},c.prototype.readUInt8=function(e,t){return t||D(e,1,this.length),this[e]},c.prototype.readUInt16LE=function(e,t){return t||D(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUInt16BE=function(e,t){return t||D(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUInt32LE=function(e,t){return t||D(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUInt32BE=function(e,t){return t||D(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},c.prototype.readInt8=function(e,t){return t||D(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},c.prototype.readInt16LE=function(e,t){t||D(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(e,t){t||D(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(e,t){return t||D(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return t||D(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!1,52,8)},c.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||O(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},c.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,255,0),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},c.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},c.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},c.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},c.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,127,-128),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},c.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},c.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},c.prototype.writeDoubleLE=function(e,t,n){return j(this,e,t,!0,n)},c.prototype.writeDoubleBE=function(e,t,n){return j(this,e,t,!1,n)},c.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!c.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(9))},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}()},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.write=function(t){return""+t+e.RecordSeparator},e.parse=function(t){if(t[t.length-1]!==e.RecordSeparator)throw new Error("Message is incomplete.");var n=t.split(e.RecordSeparator);return n.pop(),n},e.RecordSeparatorCode=30,e.RecordSeparator=String.fromCharCode(e.RecordSeparatorCode),e}()},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r=n(23),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(21);i.inherits=n(15);var a=n(36),s=n(41);i.inherits(f,a);for(var c=o(s.prototype),u=0;u=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(u(i)&&u(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(c(i))throw new Error("Not implemented: moving existing logical children");var a=u(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=c,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return u(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=u,t.permuteLogicalChildren=function(e,t){var n=u(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=c(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t,n,r){var o=u();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),a=o.invokeDotNetFromJS(e,t,n,i);return a?f(a):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function c(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var a=o++,s=new Promise(function(e,t){n[a]={resolve:e,reject:t}});try{var c=JSON.stringify(i,g);u().beginInvokeDotNetFromJS(a,e,t,r,c)}catch(e){l(a,!1,e)}return s}function u(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=a,e.invokeMethod=function(e,t){for(var n=[],r=2;r1)for(var n=1;nthis.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,c=this._offset(n),u=r-n,l=u,f=s&&t||0,h=c[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;e0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),c=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=c),l(r,e,r.depth)}function c(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function u(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&C(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(C(n)){var c=n.name?": "+n.name:"";return e.stylize("[Function"+c+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var u,w="",_=!1,I=["{","}"];(p(n)&&(_=!0,I=["[","]"]),C(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||_&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),u=_?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(u,w,I)):I[0]+w+I[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,c;if((c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(s=e.stylize("[Setter]","special")),k(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(c.value)<0?(s=g(n)?l(e,c.value,null):l(e,c.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),b(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===_(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===_(e)}function S(e){return w(e)&&("[object Error]"===_(e)||e instanceof Error)}function C(e){return"function"==typeof e}function _(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=C,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(54);var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":"),[e.getDate(),T[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(55),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function x(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):T(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function _(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(I,e):I(e))}function I(e){p("emit readable"),e.emit("readable"),R(e)}function T(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=u.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function O(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function M(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?O(this):_(this),null;if(0===(e=C(e,t))&&t.ended)return 0===t.length&&O(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?D(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&O(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function u(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,R(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==M(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&a.length>o&&!a.warned){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,s=c,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=o[e];if(void 0===c)return!1;if("function"==typeof c)i(c,this,t);else{var u=c.length,l=d(c,u);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(37).EventEmitter},function(e,t,n){"use strict";var r=n(23);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(61).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=u,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(23);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var s,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var u=n(21);u.inherits=n(15);var l={deprecate:n(64)},f=n(38),h=n(14).Buffer,p=o.Uint8Array||function(){};var d,g=n(39);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,u=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(_,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),_(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?c(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function b(e){if(s=s||n(10),!(d.call(b,this)||this instanceof s))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),_(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,c=!0;n;)o[s]=n,n.isBuf||(c=!1),n=n.next,s+=1;o.allBuffers=c,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var u=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:u.length,u,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),_(e,t)})}function _(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(C,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}u.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,_(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(20),n(62).setImmediate,n(9))},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(21);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length=200&&c.statusCode<300?r(new a.b(c.statusCode,c.statusMessage||"",u)):o(new i.b(c.statusMessage||"",c.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(a.a)}).call(this,n(6).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(8),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var a=new Uint8Array(t);if(-1===(c=a.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var s=c+1;n=String.fromCharCode.apply(null,a.slice(0,s)),i=a.byteLength>s?a.slice(s).buffer:null}else{var c,u=t;if(-1===(c=u.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=c+1;n=u.substring(0,s),i=u.length>s?u.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(6).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a},a=this&&this.__spread||function(){for(var e=[],t=0;t0?r-4:r,f=0;f>16&255,s[c++]=t>>8&255,s[c++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[c++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[c++]=t>>8&255,s[c++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;as?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,c=a.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,c=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-u;else{if(i===c)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=u}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,c,u=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-a))<1&&(a--,c*=2),(t+=a+f>=1?h/c:h*Math.pow(2,1-f))*c>=2&&(a++,c/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*c-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<0;e[n+p]=255&a,p+=d,a/=256,u-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ +var r=n(50),o=n(51),i=n(52);function a(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,c=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,c/=2,n/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;is&&(n=s-c),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function _(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function I(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:u>223?3:u>191?2:1;if(o+f<=n)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(i=e[o+1]))&&(c=(31&u)<<6|63&i)>127&&(l=c);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(c=(15&u)<<12|(63&i)<<6|63&a)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(c=(15&u)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return x(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return _(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},c.prototype.equals=function(e){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===c.compare(this,e)},c.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},c.prototype.compare=function(e,t,n,r,o){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),u=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function O(e,t,n,r,o,i){if(!c.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function M(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function A(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||A(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function j(e,t,n,r,i){return i||A(e,0,n,8),o.write(e,t,n,r,52,8),n+8}c.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},c.prototype.readUInt8=function(e,t){return t||D(e,1,this.length),this[e]},c.prototype.readUInt16LE=function(e,t){return t||D(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUInt16BE=function(e,t){return t||D(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUInt32LE=function(e,t){return t||D(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUInt32BE=function(e,t){return t||D(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},c.prototype.readInt8=function(e,t){return t||D(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},c.prototype.readInt16LE=function(e,t){t||D(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(e,t){t||D(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(e,t){return t||D(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return t||D(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!1,52,8)},c.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||O(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},c.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,255,0),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},c.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},c.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},c.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},c.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,127,-128),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},c.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},c.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},c.prototype.writeDoubleLE=function(e,t,n){return j(this,e,t,!0,n)},c.prototype.writeDoubleBE=function(e,t,n){return j(this,e,t,!1,n)},c.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!c.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(9))},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}()},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.write=function(t){return""+t+e.RecordSeparator},e.parse=function(t){if(t[t.length-1]!==e.RecordSeparator)throw new Error("Message is incomplete.");var n=t.split(e.RecordSeparator);return n.pop(),n},e.RecordSeparatorCode=30,e.RecordSeparator=String.fromCharCode(e.RecordSeparatorCode),e}()},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r=n(23),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(21);i.inherits=n(15);var a=n(36),s=n(41);i.inherits(f,a);for(var c=o(s.prototype),u=0;u=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(u(i)&&u(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(c(i))throw new Error("Not implemented: moving existing logical children");var a=u(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=c,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return u(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=u,t.permuteLogicalChildren=function(e,t){var n=u(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=c(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t,n,r){var o=u();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),a=o.invokeDotNetFromJS(e,t,n,i);return a?f(a):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function c(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var a=o++,s=new Promise(function(e,t){n[a]={resolve:e,reject:t}});try{var c=JSON.stringify(i,g);u().beginInvokeDotNetFromJS(a,e,t,r,c)}catch(e){l(a,!1,e)}return s}function u(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=a,e.invokeMethod=function(e,t){for(var n=[],r=2;r1)for(var n=1;nthis.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,c=this._offset(n),u=r-n,l=u,f=s&&t||0,h=c[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;e0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),c=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=c),l(r,e,r.depth)}function c(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function u(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&C(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(C(n)){var c=n.name?": "+n.name:"";return e.stylize("[Function"+c+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var u,w="",_=!1,I=["{","}"];(p(n)&&(_=!0,I=["[","]"]),C(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||_&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),u=_?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(u,w,I)):I[0]+w+I[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,c;if((c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(s=e.stylize("[Setter]","special")),k(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(c.value)<0?(s=g(n)?l(e,c.value,null):l(e,c.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),b(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===_(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===_(e)}function S(e){return w(e)&&("[object Error]"===_(e)||e instanceof Error)}function C(e){return"function"==typeof e}function _(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=C,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(54);var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":"),[e.getDate(),T[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(55),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function x(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):T(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function _(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(I,e):I(e))}function I(e){p("emit readable"),e.emit("readable"),R(e)}function T(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=u.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function O(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function M(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?O(this):_(this),null;if(0===(e=C(e,t))&&t.ended)return 0===t.length&&O(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?D(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&O(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function u(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,R(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==M(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&a.length>o&&!a.warned){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,s=c,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=o[e];if(void 0===c)return!1;if("function"==typeof c)i(c,this,t);else{var u=c.length,l=d(c,u);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(37).EventEmitter},function(e,t,n){"use strict";var r=n(23);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(61).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=u,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(23);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var s,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var u=n(21);u.inherits=n(15);var l={deprecate:n(64)},f=n(38),h=n(14).Buffer,p=o.Uint8Array||function(){};var d,g=n(39);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,u=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(_,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),_(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?c(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function b(e){if(s=s||n(10),!(d.call(b,this)||this instanceof s))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),_(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,c=!0;n;)o[s]=n,n.isBuf||(c=!1),n=n.next,s+=1;o.allBuffers=c,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var u=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:u.length,u,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),_(e,t)})}function _(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(C,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}u.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,_(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(20),n(62).setImmediate,n(9))},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(21);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length=200&&c.statusCode<300?r(new a.b(c.statusCode,c.statusMessage||"",u)):o(new i.b(c.statusMessage||"",c.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(a.a)}).call(this,n(6).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(8),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var a=new Uint8Array(t);if(-1===(c=a.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var s=c+1;n=String.fromCharCode.apply(null,a.slice(0,s)),i=a.byteLength>s?a.slice(s).buffer:null}else{var c,u=t;if(-1===(c=u.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=c+1;n=u.substring(0,s),i=u.length>s?u.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(6).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a},a=this&&this.__spread||function(){for(var e=[],t=0;t0?r-4:r,f=0;f>16&255,s[c++]=t>>8&255,s[c++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[c++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[c++]=t>>8&255,s[c++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;as?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,c=a.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,c=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-u;else{if(i===c)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=u}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,c,u=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-a))<1&&(a--,c*=2),(t+=a+f>=1?h/c:h*Math.pow(2,1-f))*c>=2&&(a++,c/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*c-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<0;e[n+p]=255&a,p+=d,a/=256,u-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ -function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(35).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;ai)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="3.1.0-dev"}]); \ No newline at end of file +function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(34).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;ai)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="0.0.0-DEV_BUILD"}]); \ No newline at end of file diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js new file mode 100644 index 000000000000..0ffca1d4e249 --- /dev/null +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u>2,r=Module.HEAPU32[n+1];if(r>g)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*y+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var E=document.createElement("a");function _(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file From 3c06726d77cc40580558eababbc45cb4f9e6daeb Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 22 Nov 2019 14:59:52 -0800 Subject: [PATCH 009/322] Move Mono.WebAssembly.Interop to blazor-wasm branch --- eng/ProjectReferences.props | 1 + eng/Version.Details.xml | 4 - eng/Versions.props | 1 - ...rosoft.AspNetCore.Blazor.HttpClient.csproj | 2 +- .../src/InternalCalls.cs | 25 +++ .../src/Mono.WebAssembly.Interop.csproj | 17 ++ .../src/MonoWebAssemblyJSRuntime.cs | 157 ++++++++++++++++++ src/Components/Components.sln | 18 ++ src/Components/ComponentsNoDeps.slnf | 1 + 9 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs create mode 100644 src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj create mode 100644 src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index 3ac3e8dbf677..d170c5aa246a 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -15,6 +15,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e5f59d2cb63e..92ed43ccfb64 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -289,10 +289,6 @@ https://github.com/aspnet/Extensions 4ebd75b961136c7ca331866eed3403becda75681 - - https://github.com/aspnet/Extensions - 4ebd75b961136c7ca331866eed3403becda75681 - https://github.com/dotnet/corefx 0f7f38c4fd323b26da10cce95f857f77f0f09b48 diff --git a/eng/Versions.props b/eng/Versions.props index 4c61494afafc..e2dd6a11fe8e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -158,7 +158,6 @@ 3.1.0 3.1.0-rtm.19568.3 3.1.0 - 3.1.0-preview4.19568.3 3.1.0 3.1.0 diff --git a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj index be140d936e27..18bdc5e1fe28 100644 --- a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj +++ b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj @@ -1,7 +1,7 @@ - netstandard2.1 + netstandard2.0 Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly. true diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs b/src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs new file mode 100644 index 000000000000..60c0cdc42913 --- /dev/null +++ b/src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs @@ -0,0 +1,25 @@ +// 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 +{ + /// + /// Methods that map to the functions compiled into the Mono WebAssembly runtime, + /// as defined by 'mono_add_internal_call' calls in driver.c + /// + 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(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2); + } +} diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj b/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj new file mode 100644 index 000000000000..ea714b2d92dc --- /dev/null +++ b/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.1 + Abstractions and features for interop between Mono WebAssembly and JavaScript code. + wasm;javascript;interop + true + true + true + false + + + + + + + diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs b/src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs new file mode 100644 index 000000000000..654263a12331 --- /dev/null +++ b/src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs @@ -0,0 +1,157 @@ +// 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.Text.Json; +using Microsoft.JSInterop; +using Microsoft.JSInterop.Infrastructure; +using WebAssembly.JSInterop; + +namespace Mono.WebAssembly.Interop +{ + /// + /// Provides methods for invoking JavaScript functions for applications running + /// on the Mono WebAssembly runtime. + /// + public class MonoWebAssemblyJSRuntime : JSInProcessRuntime + { + /// + /// Gets the used to perform operations using . + /// + private static MonoWebAssemblyJSRuntime Instance { get; set; } + + /// + /// Initializes the to be used to perform operations using . + /// + /// The instance. + protected static void Initialize(MonoWebAssemblyJSRuntime jsRuntime) + { + if (Instance != null) + { + throw new InvalidOperationException("MonoWebAssemblyJSRuntime has already been initialized."); + } + + Instance = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime)); + } + + /// + protected override string InvokeJS(string identifier, string argsJson) + { + var noAsyncHandle = default(long); + var result = InternalCalls.InvokeJSMarshalled(out var exception, ref noAsyncHandle, identifier, argsJson); + return exception != null + ? throw new JSException(exception) + : result; + } + + /// + protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson) + { + InternalCalls.InvokeJSMarshalled(out _, ref asyncHandle, identifier, argsJson); + } + + // Invoked via Mono's JS interop mechanism (invoke_method) + private static string InvokeDotNet(string assemblyName, string methodIdentifier, string dotNetObjectId, string argsJson) + { + var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId == null ? default : long.Parse(dotNetObjectId), callId: null); + return DotNetDispatcher.Invoke(Instance, callInfo, argsJson); + } + + // Invoked via Mono's JS interop mechanism (invoke_method) + private static void EndInvokeJS(string argsJson) + => DotNetDispatcher.EndInvokeJS(Instance, argsJson); + + // Invoked via Mono's JS interop mechanism (invoke_method) + private static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson) + { + // Figure out whether 'assemblyNameOrDotNetObjectId' is the assembly name or the instance ID + // We only need one for any given call. This helps to work around the limitation that we can + // only pass a maximum of 4 args in a call from JS to Mono WebAssembly. + string assemblyName; + long dotNetObjectId; + if (char.IsDigit(assemblyNameOrDotNetObjectId[0])) + { + dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId); + assemblyName = null; + } + else + { + dotNetObjectId = default; + assemblyName = assemblyNameOrDotNetObjectId; + } + + var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId); + DotNetDispatcher.BeginInvokeDotNet(Instance, callInfo, argsJson); + } + + protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult) + { + // For failures, the common case is to call EndInvokeDotNet with the Exception object. + // For these we'll serialize as something that's useful to receive on the JS side. + // If the value is not an Exception, we'll just rely on it being directly JSON-serializable. + var resultOrError = dispatchResult.Success ? dispatchResult.Result : dispatchResult.Exception.ToString(); + + // We pass 0 as the async handle because we don't want the JS-side code to + // send back any notification (we're just providing a result for an existing async call) + var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions); + BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args); + } + + #region Custom MonoWebAssemblyJSRuntime methods + + /// + /// Invokes the JavaScript function registered with the specified identifier. + /// + /// The .NET type corresponding to the function's return value type. + /// The identifier used when registering the target function. + /// The result of the function invocation. + public TRes InvokeUnmarshalled(string identifier) + => InvokeUnmarshalled(identifier, null, null, null); + + /// + /// Invokes the JavaScript function registered with the specified identifier. + /// + /// The type of the first argument. + /// The .NET type corresponding to the function's return value type. + /// The identifier used when registering the target function. + /// The first argument. + /// The result of the function invocation. + public TRes InvokeUnmarshalled(string identifier, T0 arg0) + => InvokeUnmarshalled(identifier, arg0, null, null); + + /// + /// Invokes the JavaScript function registered with the specified identifier. + /// + /// The type of the first argument. + /// The type of the second argument. + /// The .NET type corresponding to the function's return value type. + /// The identifier used when registering the target function. + /// The first argument. + /// The second argument. + /// The result of the function invocation. + public TRes InvokeUnmarshalled(string identifier, T0 arg0, T1 arg1) + => InvokeUnmarshalled(identifier, arg0, arg1, null); + + /// + /// Invokes the JavaScript function registered with the specified identifier. + /// + /// The type of the first argument. + /// The type of the second argument. + /// The type of the third argument. + /// The .NET type corresponding to the function's return value type. + /// The identifier used when registering the target function. + /// The first argument. + /// The second argument. + /// The third argument. + /// The result of the function invocation. + public TRes InvokeUnmarshalled(string identifier, T0 arg0, T1 arg1, T2 arg2) + { + var result = InternalCalls.InvokeJSUnmarshalled(out var exception, identifier, arg0, arg1, arg2); + return exception != null + ? throw new JSException(exception) + : result; + } + + #endregion + } +} diff --git a/src/Components/Components.sln b/src/Components/Components.sln index ba0b2476ffb3..36cde86285d3 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -246,6 +246,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{A5617A9D-C71E-44DE-936C-27611EB40A02}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1516,6 +1520,18 @@ Global {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x64.Build.0 = Release|Any CPU {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.ActiveCfg = Release|Any CPU {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.Build.0 = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.ActiveCfg = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.Build.0 = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.ActiveCfg = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.Build.0 = Debug|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.Build.0 = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.ActiveCfg = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.Build.0 = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.ActiveCfg = Release|Any CPU + {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1629,6 +1645,8 @@ Global {FD9BD646-9D50-42ED-A3E1-90558BA0C6B2} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {B70F90C7-2696-4050-B24E-BF0308F4E059} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} + {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} + {D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE} diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf index 09f6a0859f95..61501c51010a 100644 --- a/src/Components/ComponentsNoDeps.slnf +++ b/src/Components/ComponentsNoDeps.slnf @@ -17,6 +17,7 @@ "Blazor\\Templates\\src\\Microsoft.AspNetCore.Blazor.Templates.csproj", "Blazor\\Validation\\src\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "Blazor\\Validation\\test\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", + "Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj", "Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", "Blazor\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj", "Blazor\\testassets\\Microsoft.AspNetCore.Blazor.E2EPerformance\\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj", From e470aead3e842b2a9229d87bb1b097465bbfea73 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 22 Nov 2019 16:42:52 -0800 Subject: [PATCH 010/322] Remove reference assembly for Blazor.HttpClient --- eng/ProjectReferences.props | 2 +- ...crosoft.AspNetCore.Blazor.HttpClient.csproj | 10 ---------- ...NetCore.Blazor.HttpClient.netstandard2.1.cs | 18 ------------------ ...crosoft.AspNetCore.Blazor.HttpClient.csproj | 1 + 4 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj delete mode 100644 src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index d170c5aa246a..2d76a7678565 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -15,6 +15,7 @@ + @@ -137,7 +138,6 @@ - diff --git a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj deleted file mode 100644 index 6a3ca4305dae..000000000000 --- a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - netstandard2.1 - - - - - - diff --git a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs b/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs deleted file mode 100644 index f6caefbe3ecc..000000000000 --- a/src/Components/Blazor/Http/ref/Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.1.cs +++ /dev/null @@ -1,18 +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 -{ - public static partial class HttpClientJsonExtensions - { - [System.Diagnostics.DebuggerStepThroughAttribute] - public static System.Threading.Tasks.Task GetJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri) { throw null; } - public static System.Threading.Tasks.Task PostJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; } - public static System.Threading.Tasks.Task PostJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; } - public static System.Threading.Tasks.Task PutJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; } - public static System.Threading.Tasks.Task PutJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; } - public static System.Threading.Tasks.Task SendJsonAsync(this System.Net.Http.HttpClient httpClient, System.Net.Http.HttpMethod method, string requestUri, object content) { throw null; } - [System.Diagnostics.DebuggerStepThroughAttribute] - public static System.Threading.Tasks.Task SendJsonAsync(this System.Net.Http.HttpClient httpClient, System.Net.Http.HttpMethod method, string requestUri, object content) { throw null; } - } -} diff --git a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj index 18bdc5e1fe28..ae4ee9a8a81b 100644 --- a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj +++ b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj @@ -4,6 +4,7 @@ netstandard2.0 Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly. true + false From e862ce7cee740dc4c1163b9629cfdffbabc34bcc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 25 Nov 2019 10:09:06 -0800 Subject: [PATCH 011/322] Use a task to launch the linker (#17313) * Use a task to launch the linker Fixes https://github.com/aspnet/AspNetCore/issues/17264 --- .../Tasks/BlazorCreateRootDescriptorFile.cs | 56 ++++++ .../Blazor/Build/src/Tasks/BlazorILLink.cs | 189 ++++++++++++++++++ .../src/targets/Blazor.MonoRuntime.targets | 86 ++++---- .../BlazorCreateRootDescriptorFileTest.cs | 38 ++++ 4 files changed, 325 insertions(+), 44 deletions(-) create mode 100644 src/Components/Blazor/Build/src/Tasks/BlazorCreateRootDescriptorFile.cs create mode 100644 src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs create mode 100644 src/Components/Blazor/Build/test/BlazorCreateRootDescriptorFileTest.cs diff --git a/src/Components/Blazor/Build/src/Tasks/BlazorCreateRootDescriptorFile.cs b/src/Components/Blazor/Build/src/Tasks/BlazorCreateRootDescriptorFile.cs new file mode 100644 index 000000000000..1aa853685671 --- /dev/null +++ b/src/Components/Blazor/Build/src/Tasks/BlazorCreateRootDescriptorFile.cs @@ -0,0 +1,56 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Microsoft.AspNetCore.Blazor.Build +{ + // Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/CreateRootDescriptorFile.cs + public class BlazorCreateRootDescriptorFile : Task + { + [Required] + public ITaskItem[] AssemblyNames { get; set; } + + [Required] + public ITaskItem RootDescriptorFilePath { get; set; } + + public override bool Execute() + { + using var fileStream = File.Create(RootDescriptorFilePath.ItemSpec); + var assemblyNames = AssemblyNames.Select(a => a.ItemSpec); + + WriteRootDescriptor(fileStream, assemblyNames); + return true; + } + + internal static void WriteRootDescriptor(Stream stream, IEnumerable assemblyNames) + { + var roots = new XElement("linker"); + foreach (var assemblyName in assemblyNames) + { + roots.Add(new XElement("assembly", + new XAttribute("fullname", assemblyName), + new XElement("type", + new XAttribute("fullname", "*"), + new XAttribute("required", "true")))); + } + + var xmlWriterSettings = new XmlWriterSettings + { + Indent = true, + OmitXmlDeclaration = true + }; + + using var writer = XmlWriter.Create(stream, xmlWriterSettings); + var xDocument = new XDocument(roots); + + xDocument.Save(writer); + } + } +} diff --git a/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs new file mode 100644 index 000000000000..527f302a463c --- /dev/null +++ b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs @@ -0,0 +1,189 @@ +// 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.Blazor.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() => ILLinkPath; + + 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(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 exited 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); + } + } + } +} diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 26cd58d0c12c..beeb6cfcccb0 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -97,6 +97,13 @@ <_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" /> + + <_WebAssemblyBCLFolder Include=" + $(DotNetWebAssemblyBCLPath); + $(DotNetWebAssemblyBCLFacadesPath); + $(DotNetWebAssemblyFrameworkPath)" /> + + <_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" /> @@ -119,7 +126,7 @@ + DependsOnTargets="_GenerateBlazorLinkerDescriptor;_LinkBlazorApplication"> @@ -133,36 +140,27 @@ - + - - <_PrepareLinkerDescriptorAssemblyLine Include="@(IntermediateAssembly->'%(FileName)')" /> - <_GeneratedLinkerDescriptorLine Include="<linker>" /> - <_GeneratedLinkerDescriptorLine Include="@(_PrepareLinkerDescriptorAssemblyLine->'<assembly fullname="%(Identity)" />')" /> - <_GeneratedLinkerDescriptorLine Include="</linker>" /> - - - + - - - - + + + - <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)"> - $([System.String]::Copy('%(RelativeDir)').TrimEnd('\').TrimEnd('/')) - true - - - - <_WebAssemblyBCLFolder Include="$(DotNetWebAssemblyBCLPath);$(DotNetWebAssemblyBCLFacadesPath);$(DotNetWebAssemblyFrameworkPath)" /> - <_BlazorAssembliesToCopy Include="@(IntermediateAssembly->'-a "%(FullPath)"')" /> - <_BlazorFolderLookupPaths Include="@(_WebAssemblyBCLFolder->'-d "%(Identity)"')" /> - - - <_BlazorFolderLookupPaths Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" Include="@(_BlazorDependencyAssembly->'-d "%(RelativeDirNoTrailingSlash)"')" /> + <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)" IsLinkable="$([System.String]::Copy('%(FileName)').StartsWith('System.'))" /> - - <_BlazorAssembliesToCopy Condition="'%(_BlazorDependencyAssembly.IsLinkable)' != 'true'" Include="@(_BlazorDependencyAssembly->'-a "%(FullPath)"')" /> + <_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" /> + <_BlazorAssemblyToLink Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" /> - <_BlazorAssemblyDescriptorFiles - Include="@(BlazorLinkerDescriptor->'-x "%(FullPath)"')" Condition="'@(BlazorLinkerDescriptor)' != ''" /> + <_BlazorLinkerRoot Include="@(IntermediateAssembly)" /> + <_BlazorLinkerRoot Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' != 'true'" /> <_BlazorLinkerAdditionalOptions>-l $(MonoLinkerI18NAssemblies) $(AdditionalMonoLinkerOptions) - <_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> - - + + + <_DotNetHostDirectory>$(NetCoreRoot) + <_DotNetHostFileName>dotnet + <_DotNetHostFileName Condition=" '$(OS)' == 'Windows_NT' ">dotnet.exe + + + <_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> @@ -214,6 +217,7 @@ + - - - <_WebAssemblyBCLFolder Include="$(DotNetWebAssemblyBCLPath);$(DotNetWebAssemblyBCLFacadesPath);$(DotNetWebAssemblyFrameworkPath)" /> - <_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" /> - - + --> Date: Mon, 25 Nov 2019 13:00:24 -0800 Subject: [PATCH 012/322] Enable WASM debugging (#17162) Changes needed so VS can connect to the Mono WebAssembly debugger via Chrome protocol --- ...lazorMonoDebugProxyAppBuilderExtensions.cs | 127 ++++++++++++++++-- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs index 533cd9939985..7ce7544c9b84 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs @@ -9,9 +9,9 @@ using System.Net; using System.Net.Http; using System.Runtime.InteropServices; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Newtonsoft.Json; using WsProxy; namespace Microsoft.AspNetCore.Builder @@ -21,6 +21,15 @@ namespace Microsoft.AspNetCore.Builder /// public static class BlazorMonoDebugProxyAppBuilderExtensions { + private static JsonSerializerOptions JsonOptions = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + IgnoreNullValues = true + }; + + private static string DefaultDebuggerHost = "http://localhost:9222"; + /// /// Adds middleware for needed for debugging Blazor applications /// inside Chromium dev tools. @@ -29,6 +38,8 @@ public static void UseBlazorDebugging(this IApplicationBuilder app) { app.UseWebSockets(); + app.UseVisualStudioDebuggerConnectionRequestHandlers(); + app.Use((context, next) => { var requestPath = context.Request.Path; @@ -52,6 +63,85 @@ public static void UseBlazorDebugging(this IApplicationBuilder app) }); } + private static string GetDebuggerHost() + { + var envVar = Environment.GetEnvironmentVariable("ASPNETCORE_WEBASSEMBLYDEBUGHOST"); + + if (string.IsNullOrEmpty(envVar)) + { + return DefaultDebuggerHost; + } + else + { + return envVar; + } + } + + private static int GetDebuggerPort() + { + var host = GetDebuggerHost(); + return new Uri(host).Port; + } + + private static void UseVisualStudioDebuggerConnectionRequestHandlers(this IApplicationBuilder app) + { + // Unfortunately VS doesn't send any deliberately distinguishing information so we know it's + // not a regular browser or API client. The closest we can do is look for the *absence* of a + // User-Agent header. In the future, we should try to get VS to send a special header to indicate + // this is a debugger metadata request. + app.Use(async (context, next) => + { + var request = context.Request; + var requestPath = request.Path; + if (requestPath.StartsWithSegments("/json") + && !request.Headers.ContainsKey("User-Agent")) + { + if (requestPath.Equals("/json", StringComparison.OrdinalIgnoreCase) || requestPath.Equals("/json/list", StringComparison.OrdinalIgnoreCase)) + { + var availableTabs = await GetOpenedBrowserTabs(); + + // Filter the list to only include tabs displaying the requested app, + // but only during the "choose application to debug" phase. We can't apply + // the same filter during the "connecting" phase (/json/list), nor do we need to. + if (requestPath.Equals("/json")) + { + availableTabs = availableTabs.Where(tab => tab.Url.StartsWith($"{request.Scheme}://{request.Host}{request.PathBase}/")); + } + + var proxiedTabInfos = availableTabs.Select(tab => + { + var underlyingV8Endpoint = tab.WebSocketDebuggerUrl; + var proxiedV8Endpoint = $"ws://{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}"; + return new + { + description = "", + devtoolsFrontendUrl = "", + id = tab.Id, + title = tab.Title, + type = tab.Type, + url = tab.Url, + webSocketDebuggerUrl = proxiedV8Endpoint + }; + }); + + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(JsonSerializer.Serialize(proxiedTabInfos)); + } + else if (requestPath.Equals("/json/version", StringComparison.OrdinalIgnoreCase)) + { + var browserVersionJson = await GetBrowserVersionInfoAsync(); + + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(browserVersionJson); + } + } + else + { + await next(); + } + }); + } + private static async Task DebugWebSocketProxyRequest(HttpContext context) { if (!context.WebSockets.IsWebSocketRequest) @@ -81,13 +171,13 @@ private static async Task DebugHome(HttpContext context) // TODO: Allow overriding port (but not hostname, as we're connecting to the // local browser, not to the webserver serving the app) - var debuggerHost = "http://localhost:9222"; + var debuggerHost = GetDebuggerHost(); var debuggerTabsListUrl = $"{debuggerHost}/json"; IEnumerable availableTabs; try { - availableTabs = await GetOpenedBrowserTabs(debuggerHost); + availableTabs = await GetOpenedBrowserTabs(); } catch (Exception ex) { @@ -154,21 +244,22 @@ There is more than one browser tab at {targetTabUrl}. private static string GetLaunchChromeInstructions(string appRootUrl) { var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug"); + var debuggerPort = GetDebuggerPort(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return $@"

Press Win+R and enter the following:

-

chrome --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}

"; +

chrome --remote-debugging-port={debuggerPort} --user-data-dir=""{profilePath}"" {appRootUrl}

"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return $@"

In a terminal window execute the following:

-

google-chrome --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}

"; +

google-chrome --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}

"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return $@"

Execute the following:

-

open /Applications/Google\ Chrome.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}

"; +

open /Applications/Google\ Chrome.app --args --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}

"; } else { @@ -179,16 +270,17 @@ private static string GetLaunchChromeInstructions(string appRootUrl) private static string GetLaunchEdgeInstructions(string appRootUrl) { var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug"); + var debugggerPort = GetDebuggerPort(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return $@"

Press Win+R and enter the following:

-

msedge --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}

"; +

msedge --remote-debugging-port={debugggerPort} --user-data-dir=""{profilePath}"" {appRootUrl}

"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return $@"

In a terminal window execute the following:

-

open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}

"; +

open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port={debugggerPort} --user-data-dir={profilePath} {appRootUrl}

"; } else { @@ -196,17 +288,24 @@ private static string GetLaunchEdgeInstructions(string appRootUrl) } } - private static async Task> GetOpenedBrowserTabs(string debuggerHost) + private static async Task GetBrowserVersionInfoAsync() { - using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }) - { - var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json"); - return JsonConvert.DeserializeObject(jsonResponse); - } + using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; + var debuggerHost = GetDebuggerHost(); + return await httpClient.GetStringAsync($"{debuggerHost}/json/version"); + } + + private static async Task> GetOpenedBrowserTabs() + { + using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; + var debuggerHost = GetDebuggerHost(); + var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json"); + return JsonSerializer.Deserialize(jsonResponse, JsonOptions); } class BrowserTab { + public string Id { get; set; } public string Type { get; set; } public string Url { get; set; } public string Title { get; set; } From 4400467c15ccbf6df222e5d264afb7e3b850ea0d Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 25 Nov 2019 23:16:29 +0100 Subject: [PATCH 013/322] [Blazor] Fixes publishing for standalone blazor-wasm applications (#17353) * Updates the publish path on the static web assets to match the convention used by standalone blazor applications. --- .../Blazor/Build/src/targets/All.targets | 14 +------- .../Build/src/targets/StaticWebAssets.targets | 32 +++++++++++++++++++ .../PublishIntegrationTest.cs | 12 +++++-- .../RazorClassLibrary.csproj | 8 +++++ .../razorclasslibrary/wwwroot/styles.css | 1 + .../wwwroot/wwwroot/exampleJsInterop.js | 0 .../testassets/standalone/standalone.csproj | 4 +++ .../HostedInAspNet.Client.csproj | 13 -------- 8 files changed, 56 insertions(+), 28 deletions(-) create mode 100644 src/Components/Blazor/Build/src/targets/StaticWebAssets.targets create mode 100644 src/Components/Blazor/Build/testassets/razorclasslibrary/RazorClassLibrary.csproj create mode 100644 src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/styles.css create mode 100644 src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/wwwroot/exampleJsInterop.js diff --git a/src/Components/Blazor/Build/src/targets/All.targets b/src/Components/Blazor/Build/src/targets/All.targets index cff950dae773..6aa60e822760 100644 --- a/src/Components/Blazor/Build/src/targets/All.targets +++ b/src/Components/Blazor/Build/src/targets/All.targets @@ -17,6 +17,7 @@ + @@ -42,17 +43,4 @@ - - - $(GetCurrentProjectStaticWebAssetsDependsOn); - _ClearCurrentStaticWebAssetsForReferenceDiscovery - - - - - - - - - diff --git a/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets b/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets new file mode 100644 index 000000000000..02af2eec64c2 --- /dev/null +++ b/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets @@ -0,0 +1,32 @@ + + + + + $(ResolveStaticWebAssetsInputsDependsOn); + _RemoveBlazorCurrentProjectAssetsFromStaticWebAssets; + + + + + + + + + + + + + + + <_StandaloneExternalPublishStaticWebAsset Include="@(_ExternalPublishStaticWebAsset)" Condition="'%(RelativePath)' != ''"> + $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$([MSBuild]::NormalizePath('$([System.Text.RegularExpressions.Regex]::Replace('%(RelativePath)','^wwwroot\\?\/?(.*)','$(BlazorPublishDistDir)$1'))'))')) + + + + + + + + + diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs index 606fb88abae6..9748e1096319 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -13,7 +13,7 @@ public class PublishIntegrationTest public async Task Publish_WithDefaultSettings_Works() { // Arrange - using var project = ProjectDirectory.Create("standalone"); + using var project = ProjectDirectory.Create("standalone", additionalProjects: new string[] { "razorclasslibrary" }); var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); Assert.BuildPassed(result); @@ -28,6 +28,10 @@ public async Task Publish_WithDefaultSettings_Works() Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + // Verify referenced static web assets + Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css"); + // Verify static assets are in the publish directory Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); @@ -39,7 +43,7 @@ public async Task Publish_WithDefaultSettings_Works() public async Task Publish_WithLinkOnBuildDisabled_Works() { // Arrange - using var project = ProjectDirectory.Create("standalone"); + using var project = ProjectDirectory.Create("standalone", additionalProjects: new string[] { "razorclasslibrary" }); project.AddProjectFileContent( @" false @@ -62,6 +66,10 @@ public async Task Publish_WithLinkOnBuildDisabled_Works() // Verify static assets are in the publish directory Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + // Verify referenced static web assets + Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css"); + // Verify web.config Assert.FileExists(result, publishDirectory, "web.config"); } diff --git a/src/Components/Blazor/Build/testassets/razorclasslibrary/RazorClassLibrary.csproj b/src/Components/Blazor/Build/testassets/razorclasslibrary/RazorClassLibrary.csproj new file mode 100644 index 000000000000..94e866815d23 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/razorclasslibrary/RazorClassLibrary.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.1 + 3.0 + + + diff --git a/src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/styles.css b/src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/styles.css new file mode 100644 index 000000000000..5f282702bb03 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/styles.css @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/wwwroot/exampleJsInterop.js b/src/Components/Blazor/Build/testassets/razorclasslibrary/wwwroot/wwwroot/exampleJsInterop.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/Components/Blazor/Build/testassets/standalone/standalone.csproj b/src/Components/Blazor/Build/testassets/standalone/standalone.csproj index 60302d4a0c40..1b13eb3d5357 100644 --- a/src/Components/Blazor/Build/testassets/standalone/standalone.csproj +++ b/src/Components/Blazor/Build/testassets/standalone/standalone.csproj @@ -13,4 +13,8 @@ + + + + diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj index cb21b79a8c0b..e27de695c1b3 100644 --- a/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj +++ b/src/Components/Blazor/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj @@ -11,17 +11,4 @@ - - - $(GetCurrentProjectStaticWebAssetsDependsOn); - _ClearCurrentStaticWebAssetsForReferenceDiscovery - - - - - - - - - From 6c961ae4e2585511cf37fe06ebc3b348b0e0008e Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 25 Nov 2019 16:17:22 -0800 Subject: [PATCH 014/322] Update branding for Blazor packages and update baseline (#17346) * Disable baseline generation in CodeCheck --- eng/Baseline.Designer.props | 576 +++++++++--------- eng/Baseline.xml | 152 +++-- eng/Versions.props | 2 +- eng/scripts/CodeCheck.ps1 | 9 +- .../BaselineGenerator.csproj | 1 - src/Components/Blazor/Directory.Build.props | 10 + 6 files changed, 379 insertions(+), 371 deletions(-) create mode 100644 src/Components/Blazor/Directory.Build.props diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props index 1e28129d002d..b5c81965354d 100644 --- a/eng/Baseline.Designer.props +++ b/eng/Baseline.Designer.props @@ -2,7 +2,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0 + 3.1.0 @@ -16,132 +16,132 @@ - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - - - + + + + - + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - - - + + + + - - - + + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - + + @@ -186,510 +186,510 @@ - 3.0.0 + 3.1.0 - - - - + + + + - - - - + + + + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - - + + + - - + + - 3.0.0 + 3.1.0 - - + + - - + + - 3.0.0 + 3.1.0 - - - - - + + + + + - - - - + + + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - - - + + + - - - + + + - - + + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - + - + - 3.0.0 - - - - - - - - - - + 3.1.0 + + + + + + + + + + - - - - - - - - - + + + + + + + + + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - + + + - - + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - + + + - - - + + + - 3.0.0 + 3.1.0 - - + + - - + + - 3.0.0 + 3.1.0 - - - + + + - - + + - 3.0.0 + 3.1.0 - - - + + + - - + + - 3.0.0 + 3.1.0 - - - - - + + + + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - - + + + + - 3.0.0 + 3.1.0 - - - - + + + + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - + + - - + + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - - - - + + + + + + - - - - - + + + + + - 3.0.0 + 3.1.0 - - - + + + - - - + + + - 3.0.0 + 3.1.0 - - + + - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - + - 3.0.0 + 3.1.0 - - - - - + + + + + - 3.0.0 + 3.1.0 - + - + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - - + + - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - - 3.0.0 + + + 3.1.0 - - - 3.0.0 + + + 3.1.0 - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - 3.0.0 + 3.1.0 - - - + + + - 3.0.0 + 3.1.0 - - - - + + + + - - - + + + - 3.0.0 + 3.1.0 - - - + + + - - + + \ No newline at end of file diff --git a/eng/Baseline.xml b/eng/Baseline.xml index 52cbb358f44a..9a5276d72971 100644 --- a/eng/Baseline.xml +++ b/eng/Baseline.xml @@ -1,91 +1,89 @@  - - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/Versions.props b/eng/Versions.props index e26ddfa77c06..15e109fae652 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -13,7 +13,7 @@ - false + true release true false diff --git a/eng/scripts/CodeCheck.ps1 b/eng/scripts/CodeCheck.ps1 index 0d9c9dfec8a5..007abebc8c18 100644 --- a/eng/scripts/CodeCheck.ps1 +++ b/eng/scripts/CodeCheck.ps1 @@ -161,10 +161,11 @@ try { & $PSScriptRoot\GenerateReferenceAssemblies.ps1 -ci:$ci } - Write-Host "Re-generating package baselines" - Invoke-Block { - & dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/" - } + # Temporarily disable package baseline generation while we stage for publishing + # Write-Host "Re-generating package baselines" + # Invoke-Block { + # & dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/" + # } Write-Host "Run git diff to check for pending changes" diff --git a/eng/tools/BaselineGenerator/BaselineGenerator.csproj b/eng/tools/BaselineGenerator/BaselineGenerator.csproj index df9cc7220a10..775e7523c847 100644 --- a/eng/tools/BaselineGenerator/BaselineGenerator.csproj +++ b/eng/tools/BaselineGenerator/BaselineGenerator.csproj @@ -3,7 +3,6 @@ Exe $(DefaultNetCoreTargetFramework) - -s https://api.nuget.org/v3/index.json $(MSBuildThisFileDirectory)../../ diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props new file mode 100644 index 000000000000..f04afda6dbb5 --- /dev/null +++ b/src/Components/Blazor/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + + 3.1.0 + preview4 + + + \ No newline at end of file From 3c6dc1c516f2312178ceb440abebc958757316b5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 26 Nov 2019 16:42:55 -0800 Subject: [PATCH 015/322] Try different MSBuild things to make build work (#17427) Fixes https://github.com/aspnet/AspNetCore/issues/17418 --- .../Blazor/Build/src/ReferenceFromSource.props | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Components/Blazor/Build/src/ReferenceFromSource.props b/src/Components/Blazor/Build/src/ReferenceFromSource.props index 884ddbad7a76..37e2b60e16f0 100644 --- a/src/Components/Blazor/Build/src/ReferenceFromSource.props +++ b/src/Components/Blazor/Build/src/ReferenceFromSource.props @@ -20,6 +20,14 @@ + + + + + false - true - TargetFramework + TargetFramework=$(DefaultNetCoreTargetFramework) false From 0c381d2402d506048492aaf31908d244989da1ee Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 26 Nov 2019 16:45:42 -0800 Subject: [PATCH 016/322] Add some tests for hosted project building and publishing (#17398) * Add some tests for hosted project building and publishing --- .../Blazor/Build/src/targets/Publish.targets | 13 +- .../BuildIntegrationTest.cs | 19 +++ .../PublishIntegrationTest.cs | 120 +++++++++++++++++- ...osoft.AspNetCore.Blazor.Build.Tests.csproj | 1 + .../Build/testassets/blazorhosted/Program.cs | 15 +++ .../blazorhosted/blazorhosted.csproj | 11 ++ 6 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/Components/Blazor/Build/testassets/blazorhosted/Program.cs create mode 100644 src/Components/Blazor/Build/testassets/blazorhosted/blazorhosted.csproj diff --git a/src/Components/Blazor/Build/src/targets/Publish.targets b/src/Components/Blazor/Build/src/targets/Publish.targets index 75c0ed5febc2..718a02e073c9 100644 --- a/src/Components/Blazor/Build/src/targets/Publish.targets +++ b/src/Components/Blazor/Build/src/targets/Publish.targets @@ -40,8 +40,17 @@ <_BlazorConfigPath>$(OutDir)$(AssemblyName).blazor.config - - + + + <_BlazorPublishConfigContent Include="." /> + <_BlazorPublishConfigContent Include="$(AssemblyName)" /> + + + diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs index ddd7fcb43bd2..1cc39f0d6ec7 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs @@ -28,6 +28,25 @@ public async Task Build_WithDefaultSettings_Works() Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. } + [Fact] + public async Task Build_Hosted_Works() + { + // Arrange + using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", }); + project.TargetFramework = "netcoreapp3.1"; + var result = await MSBuildProcessManager.DotnetMSBuild(project); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + var blazorConfig = Path.Combine(buildOutputDirectory, "standalone.blazor.config"); + Assert.FileExists(result, blazorConfig); + + var path = Path.GetFullPath(Path.Combine(project.SolutionPath, "standalone", "bin", project.Configuration, "netstandard2.1", "standalone.dll")); + Assert.FileContains(result, blazorConfig, path); + Assert.FileDoesNotExist(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); + } + [Fact] public async Task Build_WithLinkOnBuildDisabled_Works() { diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs index 9748e1096319..2c2ddd7e97e2 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -13,7 +13,7 @@ public class PublishIntegrationTest public async Task Publish_WithDefaultSettings_Works() { // Arrange - using var project = ProjectDirectory.Create("standalone", additionalProjects: new string[] { "razorclasslibrary" }); + using var project = ProjectDirectory.Create("standalone", additionalProjects: new [] { "razorclasslibrary" }); var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); Assert.BuildPassed(result); @@ -39,11 +39,49 @@ public async Task Publish_WithDefaultSettings_Works() Assert.FileExists(result, publishDirectory, "web.config"); } + [Fact] + public async Task Publish_WithNoBuild_Works() + { + // Arrange + using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" }); + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build"); + + Assert.BuildPassed(result); + + result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:NoBuild=true"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath)); + + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify static web assets from referenced projects are copied. + // Uncomment once https://github.com/aspnet/AspNetCore/issues/17426 is resolved. + // Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js"); + // Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css"); + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify web.config + Assert.FileExists(result, publishDirectory, "web.config"); + } + [Fact] public async Task Publish_WithLinkOnBuildDisabled_Works() { // Arrange - using var project = ProjectDirectory.Create("standalone", additionalProjects: new string[] { "razorclasslibrary" }); + using var project = ProjectDirectory.Create("standalone", additionalProjects: new [] { "razorclasslibrary" }); project.AddProjectFileContent( @" false @@ -73,5 +111,83 @@ public async Task Publish_WithLinkOnBuildDisabled_Works() // Verify web.config Assert.FileExists(result, publishDirectory, "web.config"); } + + [Fact] + public async Task Publish_HostedApp_Works() + { + // Arrange + using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", }); + project.TargetFramework = "netcoreapp3.1"; + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + // Make sure the main project exists + Assert.FileExists(result, publishDirectory, "blazorhosted.dll"); + + var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify static web assets from referenced projects are copied. + Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js"); + Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css"); + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify web.config + Assert.FileExists(result, publishDirectory, "web.config"); + + var blazorConfig = Path.Combine(publishDirectory, "standalone.blazor.config"); + Assert.FileContains(result, blazorConfig, "."); + } + + [Fact] + public async Task Publish_HostedApp_WithNoBuild_Works() + { + // Arrange + using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", }); + project.TargetFramework = "netcoreapp3.1"; + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build"); + + Assert.BuildPassed(result); + + result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:NoBuild=true"); + + var publishDirectory = project.PublishOutputDirectory; + // Make sure the main project exists + Assert.FileExists(result, publishDirectory, "blazorhosted.dll"); + + var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify static web assets from referenced projects are copied. + // Uncomment once https://github.com/aspnet/AspNetCore/issues/17426 is resolved. + // Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js"); + // Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css"); + + // Verify static assets are in the publish directory + Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html"); + + // Verify web.config + Assert.FileExists(result, publishDirectory, "web.config"); + } } } diff --git a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj index 5b7c3827cad4..652888d604b3 100644 --- a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj +++ b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj @@ -47,6 +47,7 @@ <_TestAsset Include="..\testassets\standalone\standalone.csproj" /> + <_TestAsset Include="..\testassets\blazorhosted\blazorhosted.csproj" /> + + + netcoreapp3.1 + + + + + + + From fa010eed3246cb7e0c13035861aaf1ecacfa843e Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 27 Nov 2019 02:39:30 -0800 Subject: [PATCH 017/322] Pin external dependencies (#17437) * Pin external dependencies --- eng/Version.Details.xml | 94 ++++++++++++++++++++--------------------- eng/Versions.props | 94 ++++++++++++++++++++--------------------- 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a0a2f2c6e531..7178ef23c3a2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -69,19 +69,19 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -89,91 +89,91 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -181,11 +181,11 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -193,47 +193,47 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -241,23 +241,23 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -265,7 +265,7 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -277,7 +277,7 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 @@ -285,7 +285,7 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 diff --git a/eng/Versions.props b/eng/Versions.props index 15e109fae652..14b1124a010c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -103,61 +103,61 @@ 3.1.0-rtm.19572.8 3.1.0-rtm.19572.8 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 3.1.0-rtm.19572.8 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 3.1.0-rtm.19572.8 - 3.1.0-rtm.19572.8 + 3.1.0 3.1.0-preview4.19572.8 3.1.0-rtm.19573.1 From 46b95b25646a80ecbe38615d753e1af90bee07b6 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 26 Nov 2019 20:26:01 +0000 Subject: [PATCH 018/322] Fix wasm debugging when running on HTTPS. Fixes #17338 --- .../MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs index 7ce7544c9b84..b2e18fe3fff6 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs @@ -237,7 +237,8 @@ There is more than one browser tab at {targetTabUrl}. var underlyingV8Endpoint = tabToDebug.WebSocketDebuggerUrl; var proxyEndpoint = $"{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}"; var devToolsUrlAbsolute = new Uri(debuggerHost + tabToDebug.DevtoolsFrontendUrl); - var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?ws={proxyEndpoint}"; + var wsParamName = request.IsHttps ? "wss" : "ws"; + var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?{wsParamName}={proxyEndpoint}"; context.Response.Redirect(devToolsUrlWithProxy); } From 3579d8fca26f313146e28717ca7fabb1edec2d1d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 26 Nov 2019 20:27:50 +0000 Subject: [PATCH 019/322] Fix swapped browser names. Fixes #16746 --- .../BlazorMonoDebugProxyAppBuilderExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs index b2e18fe3fff6..405a7d12df5a 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs @@ -244,7 +244,7 @@ There is more than one browser tab at {targetTabUrl}. private static string GetLaunchChromeInstructions(string appRootUrl) { - var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug"); + var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug"); var debuggerPort = GetDebuggerPort(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -270,7 +270,7 @@ private static string GetLaunchChromeInstructions(string appRootUrl) private static string GetLaunchEdgeInstructions(string appRootUrl) { - var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug"); + var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug"); var debugggerPort = GetDebuggerPort(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) From 99883719af5f694dcbec589530a3fa28364ece75 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 26 Nov 2019 20:34:19 +0000 Subject: [PATCH 020/322] Suppress msedge first run experience when debugging --- .../MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs index 405a7d12df5a..cbe0fe363a67 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs @@ -276,7 +276,7 @@ private static string GetLaunchEdgeInstructions(string appRootUrl) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return $@"

Press Win+R and enter the following:

-

msedge --remote-debugging-port={debugggerPort} --user-data-dir=""{profilePath}"" {appRootUrl}

"; +

msedge --remote-debugging-port={debugggerPort} --user-data-dir=""{profilePath}"" --no-first-run {appRootUrl}

"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { From 16195aaa3b81d6429dde0e80d97d95cf16673422 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 27 Nov 2019 13:08:54 +0000 Subject: [PATCH 021/322] Include .pdb files in blazor.boot.json to re-enable debugging --- .../Blazor/Build/src/targets/Blazor.MonoRuntime.targets | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index beeb6cfcccb0..0a3ba70a2374 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -186,6 +186,7 @@ <_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> + <_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" /> @@ -212,6 +213,7 @@ <_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.dll" /> + <_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" Condition="'$(BlazorEnableDebugging)' == 'true'" /> From 1f15d60241b9c60ed783a263c2e5a1ea817252ed Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2019 18:51:32 +0000 Subject: [PATCH 022/322] [blazor-wasm] Update dependencies from dotnet/arcade aspnet/Blazor (#17307) * Update dependencies from https://github.com/aspnet/Blazor build 20191121.2 - Microsoft.AspNetCore.Blazor.Mono - 3.1.0-preview4.19571.2 * Update dependencies from https://github.com/aspnet/Blazor build 20191126.1 - Microsoft.AspNetCore.Blazor.Mono - 3.1.0-preview4.19576.1 * Update dependencies from https://github.com/aspnet/Blazor build 20191126.2 - Microsoft.AspNetCore.Blazor.Mono - 3.1.0-preview4.19576.2 * Add missing extensions feed Seems like the feed with stable versions has been deleted in the updated. I've re-added it and that should fix the existing restore issues. * Pass an empty array to entry point Fixes https://github.com/aspnet/AspNetCore/issues/17419 --- NuGet.config | 5 +- eng/Version.Details.xml | 16 ++-- eng/Versions.props | 4 +- .../templates/post-build/common-variables.yml | 14 ++-- .../templates/post-build/post-build.yml | 80 ++++++++++++++++++- global.json | 4 +- .../Web.JS/dist/Release/blazor.webassembly.js | 2 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 6 +- 8 files changed, 103 insertions(+), 28 deletions(-) diff --git a/NuGet.config b/NuGet.config index 6a6cb16fd280..7003d991f5cd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,16 +3,14 @@ - - - + @@ -21,5 +19,6 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7178ef23c3a2..1e00291e5176 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,9 +9,9 @@ --> - + https://github.com/aspnet/Blazor - 29e997d9e23dccbd6d53fddc95972c8da95cfe75 + 062c73f28d43b3c92bd7f46fc9667d99ec5938dc https://github.com/aspnet/AspNetCore-Tooling @@ -412,17 +412,17 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/dotnet/arcade - e34d933e18ba1cd393bbafcb6018e0f858d3e89e + 0e0d227c57e69c03427d6e668716d62cf4ceb36e - + https://github.com/dotnet/arcade - e34d933e18ba1cd393bbafcb6018e0f858d3e89e + 0e0d227c57e69c03427d6e668716d62cf4ceb36e - + https://github.com/dotnet/arcade - e34d933e18ba1cd393bbafcb6018e0f858d3e89e + 0e0d227c57e69c03427d6e668716d62cf4ceb36e https://github.com/aspnet/Extensions diff --git a/eng/Versions.props b/eng/Versions.props index 14b1124a010c..60c790687496 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,7 +62,7 @@ --> - 1.0.0-beta.19569.2 + 1.0.0-beta.19572.3 3.4.0-beta4-19569-03 @@ -96,7 +96,7 @@ 3.1.0 - 3.1.0-preview4.19572.1 + 3.1.0-preview4.19576.2 3.1.0-rtm.19572.8 3.1.0-rtm.19572.8 diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 0a2c40c1035c..216d043e4e3b 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -13,19 +13,19 @@ variables: - name: NetCore_5_Dev_Channel_Id value: 131 - # .NET Tools - Validation - - name: NetCore_Tools_Validation_Channel_Id + # .NET Eng - Validation + - name: Net_Eng_Validation_Channel_Id value: 9 - # .NET Tools - Latest - - name: NetCore_Tools_Latest_Channel_Id + # .NET Eng - Latest + - name: Net_Eng_Latest_Channel_Id value: 2 - # .NET 3 Tools - Validation - - name: NETCore_3_Tools_Validation_Channel_Id + # .NET 3 Eng - Validation + - name: NET_3_Eng_Validation_Channel_Id value: 390 - # .NET 3 Tools - Latest + # .NET 3 Eng - name: NetCore_3_Tools_Channel_Id value: 344 diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index ec80c65a923d..9921743bcdb5 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -126,8 +126,8 @@ stages: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Tools_Latest_Publish' - channelName: '.NET Tools - Latest' + stageName: 'Net_Eng_Latest_Publish' + channelName: '.NET Eng - Latest' channelId: 2 transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' @@ -138,8 +138,8 @@ stages: artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'PVR_Publish' - channelName: '.NET Tools - Validation' + stageName: 'Net_Eng_Validation_Publish' + channelName: '.NET Eng - Validation' channelId: 9 transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' @@ -264,3 +264,75 @@ stages: transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_301xx_Publishing' + channelName: '.NET Core SDK 3.0.1xx' + channelId: 556 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_301xx_Internal_Publishing' + channelName: '.NET Core SDK 3.0.1xx Internal' + channelId: 555 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_311xx_Publishing' + channelName: '.NET Core SDK 3.1.1xx' + channelId: 560 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_311xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.1xx Internal' + channelId: 559 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Publishing' + channelName: '.NET Core SDK 3.1.2xx' + channelId: 558 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_312xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.2xx Internal' + channelId: 557 + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' \ No newline at end of file diff --git a/global.json b/global.json index 5289c25502e2..1333ea9ce6e8 100644 --- a/global.json +++ b/global.json @@ -25,7 +25,7 @@ }, "msbuild-sdks": { "Yarn.MSBuild": "1.15.2", - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19569.2", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19569.2" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19572.3", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19572.3" } } diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js index 0ffca1d4e249..d125cc352fbe 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webassembly.js +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -1 +1 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u>2,r=Module.HEAPU32[n+1];if(r>g)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*y+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var E=document.createElement("a");function _(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u>2,r=Module.HEAPU32[n+1];if(r>b)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*g+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var _=document.createElement("a");function I(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 8858552747ac..31fee329d624 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -12,6 +12,7 @@ let find_class: (assemblyHandle: number, namespace: string, className: string) = let find_method: (typeHandle: number, methodName: string, unknownArg: number) => MethodHandle; let invoke_method: (method: MethodHandle, target: System_Object, argsArrayPtr: number, exceptionFlagIntPtr: number) => System_Object; let mono_call_assembly_entry_point: (assemblyName: string, args: System_Object[]) => System_Object; +let mono_obj_array_new: (length: number) => System_Object; let mono_string_get_utf8: (managedString: System_String) => Mono.Utf8Ptr; let mono_string: (jsString: string) => System_String; const appBinDirName = 'appBinDir'; @@ -41,7 +42,8 @@ export const monoPlatform: Platform = { findMethod: findMethod, callEntryPoint: function callEntryPoint(assemblyName: string): System_Object { - return mono_call_assembly_entry_point(assemblyName, []); + const empty_array = mono_obj_array_new(0); + return mono_call_assembly_entry_point(assemblyName, [empty_array]); }, callMethod: function callMethod(method: MethodHandle, target: System_Object, args: System_Object[]): System_Object { @@ -262,8 +264,10 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () ]); mono_call_assembly_entry_point = Module.mono_call_assembly_entry_point; + mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']); mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); + mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']); MONO.loaded_files = []; From 0c11c75641bad2382d8c8e99713efe579ca009be Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 27 Nov 2019 19:50:50 -0800 Subject: [PATCH 023/322] [Blazor] Fix Blazor.build package (#17463) --- .../Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec index b242d7cb1aa8..a3e099dee67e 100644 --- a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec +++ b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.nuspec @@ -11,7 +11,7 @@ - + From 548ae26e219b9c1740de45fd4a0db8b3294fcef6 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 28 Nov 2019 10:54:25 +0000 Subject: [PATCH 024/322] Fix Blazor WebAssembly hosted publishing --- src/Components/Blazor/Build/src/targets/Publish.targets | 2 +- .../test/BuildIntegrationTests/PublishIntegrationTest.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Components/Blazor/Build/src/targets/Publish.targets b/src/Components/Blazor/Build/src/targets/Publish.targets index 718a02e073c9..7cb7e0ad231d 100644 --- a/src/Components/Blazor/Build/src/targets/Publish.targets +++ b/src/Components/Blazor/Build/src/targets/Publish.targets @@ -43,7 +43,7 @@ <_BlazorPublishConfigContent Include="." /> - <_BlazorPublishConfigContent Include="$(AssemblyName)" /> + <_BlazorPublishConfigContent Include="$(AssemblyName)/" /> Date: Thu, 28 Nov 2019 23:12:44 +0100 Subject: [PATCH 025/322] [Blazor] Pins the SDK version to 3.1 and forces Blazor projects to compile against it (#17479) --- NuGet.config | 1 + eng/ProjectReferences.props | 2 +- eng/Version.Details.xml | 40 +++++++++---------- eng/Versions.props | 20 +++++----- global.json | 4 +- .../blazorhosted/blazorhosted.csproj | 1 + ...crosoft.AspNetCore.Blazor.DevServer.csproj | 7 ++-- src/Components/Blazor/Directory.Build.props | 5 ++- src/Components/Blazor/Directory.Build.targets | 1 + .../Microsoft.AspNetCore.Blazor.Server.csproj | 16 -------- ...oft.AspNetCore.Blazor.Server.netcoreapp.cs | 22 ---------- .../Microsoft.AspNetCore.Blazor.Server.csproj | 8 ++-- .../HostedInAspNet.Server.csproj | 5 ++- .../testassets/MonoSanity/MonoSanity.csproj | 4 +- src/Components/Directory.Build.props | 4 ++ src/Components/Directory.Build.targets | 20 ++++++++++ ...soft.AspNetCore.Components.E2ETests.csproj | 3 ++ .../TestServer/Components.TestServer.csproj | 8 +--- .../Infrastructure/GenerateTestProps.targets | 5 ++- 19 files changed, 84 insertions(+), 92 deletions(-) delete mode 100644 src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.csproj delete mode 100644 src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.netcoreapp.cs diff --git a/NuGet.config b/NuGet.config index 7003d991f5cd..b6e782858b75 100644 --- a/NuGet.config +++ b/NuGet.config @@ -13,6 +13,7 @@ + diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index 2d76a7678565..350c026a7d67 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -17,6 +17,7 @@ + @@ -138,7 +139,6 @@ - diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1e00291e5176..4d4af8a44a6a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,33 +29,33 @@ https://github.com/aspnet/AspNetCore-Tooling abd3c17b317dbe455b18a4f5937c43e0fc7a2944 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 - + https://github.com/aspnet/EntityFrameworkCore - a2f33c7d5125c6f3b671e55eb1bc58489041ad01 + 82c6ea483d3a17393dad5986df9a8eef89ddcd07 https://github.com/aspnet/Extensions @@ -381,21 +381,21 @@ https://github.com/dotnet/corefx 0f7f38c4fd323b26da10cce95f857f77f0f09b48 - + https://github.com/dotnet/core-setup - 9541fa09c354ea9288db00b8c1b95a34a3abdcdc + 65f04fb6db7a5e198d05dbebd5c4ad21eb018f89 - + https://github.com/dotnet/core-setup - 9541fa09c354ea9288db00b8c1b95a34a3abdcdc + 65f04fb6db7a5e198d05dbebd5c4ad21eb018f89 - + https://github.com/dotnet/core-setup - 9541fa09c354ea9288db00b8c1b95a34a3abdcdc + 65f04fb6db7a5e198d05dbebd5c4ad21eb018f89 https://github.com/dotnet/core-setup diff --git a/eng/Versions.props b/eng/Versions.props index 60c790687496..57ce7893d712 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,9 +66,9 @@ 3.4.0-beta4-19569-03 - 3.1.1-servicing.19572.8 - 3.1.1-servicing.19572.8 - 3.1.1-servicing.19572.8 + 3.1.0 + 3.1.0 + 3.1.0 2.1.0 1.1.0 @@ -160,13 +160,13 @@ 3.1.0 3.1.0-preview4.19572.8 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 + 3.1.0 3.1.0-rtm.19573.1 3.1.0-rtm.19573.1 diff --git a/global.json b/global.json index 1333ea9ce6e8..f8f800baef37 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "3.1.100-preview1-014400" + "version": "3.1.100" }, "tools": { - "dotnet": "3.1.100-preview1-014400", + "dotnet": "3.1.100", "runtimes": { "dotnet/x64": [ "$(MicrosoftNETCoreAppRuntimeVersion)" diff --git a/src/Components/Blazor/Build/testassets/blazorhosted/blazorhosted.csproj b/src/Components/Blazor/Build/testassets/blazorhosted/blazorhosted.csproj index 3b08400ff759..5a89588d8c15 100644 --- a/src/Components/Blazor/Build/testassets/blazorhosted/blazorhosted.csproj +++ b/src/Components/Blazor/Build/testassets/blazorhosted/blazorhosted.csproj @@ -2,6 +2,7 @@ netcoreapp3.1 + true diff --git a/src/Components/Blazor/DevServer/src/Microsoft.AspNetCore.Blazor.DevServer.csproj b/src/Components/Blazor/DevServer/src/Microsoft.AspNetCore.Blazor.DevServer.csproj index d18ab7c9e442..be0bd7f87bd8 100644 --- a/src/Components/Blazor/DevServer/src/Microsoft.AspNetCore.Blazor.DevServer.csproj +++ b/src/Components/Blazor/DevServer/src/Microsoft.AspNetCore.Blazor.DevServer.csproj @@ -11,15 +11,14 @@ Development server for use when building Blazor applications. false + + + true
- - - - diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props index f04afda6dbb5..9e35475c8610 100644 --- a/src/Components/Blazor/Directory.Build.props +++ b/src/Components/Blazor/Directory.Build.props @@ -6,5 +6,8 @@ 3.1.0 preview4 + + 3.1.0
- \ No newline at end of file + diff --git a/src/Components/Blazor/Directory.Build.targets b/src/Components/Blazor/Directory.Build.targets index 178608d3e5ef..e1a17eb9ca9c 100644 --- a/src/Components/Blazor/Directory.Build.targets +++ b/src/Components/Blazor/Directory.Build.targets @@ -4,4 +4,5 @@ $(PackageVersion) + diff --git a/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.csproj b/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.csproj deleted file mode 100644 index 9222fac02ff3..000000000000 --- a/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - - - - - - - - - - - - diff --git a/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.netcoreapp.cs b/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.netcoreapp.cs deleted file mode 100644 index 74cf8a6a8b6f..000000000000 --- a/src/Components/Blazor/Server/ref/Microsoft.AspNetCore.Blazor.Server.netcoreapp.cs +++ /dev/null @@ -1,22 +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.Builder -{ - public static partial class BlazorHostingApplicationBuilderExtensions - { - public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseClientSideBlazorFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string clientAssemblyFilePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseClientSideBlazorFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; } - } - public static partial class BlazorHostingEndpointRouteBuilderExtensions - { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string clientAssemblyFilePath, string filePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string clientAssemblyFilePath, string pattern, string filePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string filePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string filePath) { throw null; } - } - public static partial class BlazorMonoDebugProxyAppBuilderExtensions - { - public static void UseBlazorDebugging(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { } - } -} diff --git a/src/Components/Blazor/Server/src/Microsoft.AspNetCore.Blazor.Server.csproj b/src/Components/Blazor/Server/src/Microsoft.AspNetCore.Blazor.Server.csproj index 2d7b2d8fb4ea..0ad19d5362ce 100644 --- a/src/Components/Blazor/Server/src/Microsoft.AspNetCore.Blazor.Server.csproj +++ b/src/Components/Blazor/Server/src/Microsoft.AspNetCore.Blazor.Server.csproj @@ -4,6 +4,9 @@ $(DefaultNetCoreTargetFramework) Runtime server features for ASP.NET Core Blazor applications. true + false + + true @@ -11,11 +14,6 @@ - - - - - diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Server/HostedInAspNet.Server.csproj b/src/Components/Blazor/testassets/HostedInAspNet.Server/HostedInAspNet.Server.csproj index 224ada396362..389b41c63fbb 100644 --- a/src/Components/Blazor/testassets/HostedInAspNet.Server/HostedInAspNet.Server.csproj +++ b/src/Components/Blazor/testassets/HostedInAspNet.Server/HostedInAspNet.Server.csproj @@ -2,6 +2,9 @@ $(DefaultNetCoreTargetFramework) + + true + @@ -10,8 +13,6 @@ - - diff --git a/src/Components/Blazor/testassets/MonoSanity/MonoSanity.csproj b/src/Components/Blazor/testassets/MonoSanity/MonoSanity.csproj index 5297f5bca69a..464f63b57c23 100644 --- a/src/Components/Blazor/testassets/MonoSanity/MonoSanity.csproj +++ b/src/Components/Blazor/testassets/MonoSanity/MonoSanity.csproj @@ -2,6 +2,8 @@ $(DefaultNetCoreTargetFramework) + + true @@ -9,9 +11,7 @@ - - diff --git a/src/Components/Directory.Build.props b/src/Components/Directory.Build.props index 02d423b43e89..ef310ac60dcd 100644 --- a/src/Components/Directory.Build.props +++ b/src/Components/Directory.Build.props @@ -12,6 +12,10 @@ aspnetcore;components + + 3.1.0 + $(MSBuildThisFileDirectory)Shared\ diff --git a/src/Components/Directory.Build.targets b/src/Components/Directory.Build.targets index b992960cc31d..b6b1f773d930 100644 --- a/src/Components/Directory.Build.targets +++ b/src/Components/Directory.Build.targets @@ -3,6 +3,26 @@ true + + + + + + netcoreapp3.1 + Microsoft.AspNetCore.App + $(LatestAspNetCoreReferenceVersion) + $(LatestAspNetCoreReferenceVersion) + Microsoft.AspNetCore.App.Ref + $(LatestAspNetCoreReferenceVersion) + Microsoft.AspNetCore.App.Runtime.**RID** + linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86 + true + + + + diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj index 78fc48dc825b..ac69ac235a90 100644 --- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj +++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj @@ -7,6 +7,9 @@ $(DefaultNetCoreTargetFramework) Components.E2ETests + + true + false diff --git a/src/Components/test/testassets/TestServer/Components.TestServer.csproj b/src/Components/test/testassets/TestServer/Components.TestServer.csproj index 6c29275b2c31..a627c1160f12 100644 --- a/src/Components/test/testassets/TestServer/Components.TestServer.csproj +++ b/src/Components/test/testassets/TestServer/Components.TestServer.csproj @@ -2,18 +2,14 @@ $(DefaultNetCoreTargetFramework) + + true - - - - - - diff --git a/src/ProjectTemplates/test/Infrastructure/GenerateTestProps.targets b/src/ProjectTemplates/test/Infrastructure/GenerateTestProps.targets index 4fa71306017a..ea67b88cfa72 100644 --- a/src/ProjectTemplates/test/Infrastructure/GenerateTestProps.targets +++ b/src/ProjectTemplates/test/Infrastructure/GenerateTestProps.targets @@ -16,6 +16,9 @@ %(_TargetingPackVersionInfo.PackageVersion) $(AspNetCoreBaselineVersion) + + + $(AspNetCoreBaselineVersion) @@ -34,7 +37,7 @@ MicrosoftNETCorePlatformsPackageVersion=$(MicrosoftNETCorePlatformsPackageVersion); MicrosoftNETSdkRazorPackageVersion=$(MicrosoftNETSdkRazorPackageVersion); MicrosoftAspNetCoreAppRefPackageVersion=$(MicrosoftAspNetCoreAppRefPackageVersion); - MicrosoftAspNetCoreAppRuntimePackageVersion=@(_RuntimePackageVersionInfo->'%(PackageVersion)'); + MicrosoftAspNetCoreAppRuntimePackageVersion=$(MicrosoftAspNetCoreAppRuntimePackageVersion); SupportedRuntimeIdentifiers=$(SupportedRuntimeIdentifiers); DefaultNetCoreTargetFramework=$(DefaultNetCoreTargetFramework); From ca893e25a5f41e239a25465be54b38c685f114fd Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 29 Nov 2019 20:44:14 +0100 Subject: [PATCH 026/322] [Blazor] Fixes publish issue with static web assets on hosted scenarios (#17496) --- .../Blazor/Build/src/targets/StaticWebAssets.targets | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets b/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets index 02af2eec64c2..d547f500b13f 100644 --- a/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets +++ b/src/Components/Blazor/Build/src/targets/StaticWebAssets.targets @@ -5,6 +5,11 @@ $(ResolveStaticWebAssetsInputsDependsOn); _RemoveBlazorCurrentProjectAssetsFromStaticWebAssets; + + + $(GetCurrentProjectStaticWebAssetsDependsOn); + _RemoveBlazorCurrentProjectAssetsFromStaticWebAssets; + From 40a0173e9d9410cfdcd0c5afe33bec3e1165092f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2019 21:46:00 +0000 Subject: [PATCH 027/322] [blazor-wasm] Update dependencies from dotnet/arcade aspnet/Blazor (#17471) * Update dependencies from https://github.com/dotnet/arcade build 20191127.5 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19577.5 - Microsoft.DotNet.GenAPI - 1.0.0-beta.19577.5 - Microsoft.DotNet.Helix.Sdk - 2.0.0-beta.19577.5 * Update dependencies from https://github.com/aspnet/Blazor build 20191127.1 - Microsoft.AspNetCore.Blazor.Mono - 3.1.0-preview4.19577.1 * [Blazor] Fix Blazor.build package (#17463) * Update dependencies from https://github.com/aspnet/Blazor build 20191128.1 - Microsoft.AspNetCore.Blazor.Mono - 3.1.0-preview4.19578.1 * Fix Blazor WebAssembly hosted publishing * [Blazor] Pins the SDK version to 3.1 and forces Blazor projects to compile against it (#17479) * [Blazor] Fixes publish issue with static web assets on hosted scenarios (#17496) --- NuGet.config | 1 - eng/Version.Details.xml | 16 ++-- eng/Versions.props | 4 +- eng/common/SetupNugetSources.ps1 | 127 +++++++++++++++++++++++++++++++ eng/common/SetupNugetSources.sh | 117 ++++++++++++++++++++++++++++ global.json | 4 +- 6 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 eng/common/SetupNugetSources.ps1 create mode 100644 eng/common/SetupNugetSources.sh diff --git a/NuGet.config b/NuGet.config index b6e782858b75..1429800526b8 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,7 +10,6 @@ - diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4d4af8a44a6a..9995176df3ee 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,9 +9,9 @@ --> - + https://github.com/aspnet/Blazor - 062c73f28d43b3c92bd7f46fc9667d99ec5938dc + 9ff01af4257317a90b64959fe1c87aef3da4a36f https://github.com/aspnet/AspNetCore-Tooling @@ -412,17 +412,17 @@ https://github.com/aspnet/Extensions 1c5c7777ea9a19d54ab67ec1521665c99460efc5 - + https://github.com/dotnet/arcade - 0e0d227c57e69c03427d6e668716d62cf4ceb36e + 99c6b59a8afff97fe891341b39abe985f1d3c565 - + https://github.com/dotnet/arcade - 0e0d227c57e69c03427d6e668716d62cf4ceb36e + 99c6b59a8afff97fe891341b39abe985f1d3c565 - + https://github.com/dotnet/arcade - 0e0d227c57e69c03427d6e668716d62cf4ceb36e + 99c6b59a8afff97fe891341b39abe985f1d3c565 https://github.com/aspnet/Extensions diff --git a/eng/Versions.props b/eng/Versions.props index 57ce7893d712..f0ed1e284f4b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,7 +62,7 @@ --> - 1.0.0-beta.19572.3 + 1.0.0-beta.19577.5 3.4.0-beta4-19569-03 @@ -96,7 +96,7 @@ 3.1.0 - 3.1.0-preview4.19576.2 + 3.1.0-preview4.19578.1 3.1.0-rtm.19572.8 3.1.0-rtm.19572.8 diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1 new file mode 100644 index 000000000000..2cb40c29474b --- /dev/null +++ b/eng/common/SetupNugetSources.ps1 @@ -0,0 +1,127 @@ +# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. +# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# +# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry +# under for each Maestro managed private feed. Two additional credential +# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. +# +# This script needs to be called in every job that will restore packages and which the base repo has +# private AzDO feeds in the NuGet.config. +# +# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` +# from the AzureDevOps-Artifact-Feeds-Pats variable group. +# +# - task: PowerShell@2 +# displayName: Setup Private Feeds Credentials +# condition: eq(variables['Agent.OS'], 'Windows_NT') +# inputs: +# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 +# arguments: -ConfigFile ${Env:BUILD_SOURCESDIRECTORY}/NuGet.config -Password $Env:Token +# env: +# Token: $(dn-bot-dnceng-artifact-feeds-rw) + +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true)][string]$ConfigFile, + [Parameter(Mandatory = $true)][string]$Password +) + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +. $PSScriptRoot\tools.ps1 + +# Add source entry to PackageSources +function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $Password) { + $packageSource = $sources.SelectSingleNode("add[@key='$SourceName']") + + if ($packageSource -eq $null) + { + $packageSource = $doc.CreateElement("add") + $packageSource.SetAttribute("key", $SourceName) + $packageSource.SetAttribute("value", $SourceEndPoint) + $sources.AppendChild($packageSource) | Out-Null + } + else { + Write-Host "Package source $SourceName already present." + } + + AddCredential -Creds $creds -Source $SourceName -Username $Username -Password $Password +} + +# Add a credential node for the specified source +function AddCredential($creds, $source, $username, $password) { + # Looks for credential configuration for the given SourceName. Create it if none is found. + $sourceElement = $creds.SelectSingleNode($Source) + if ($sourceElement -eq $null) + { + $sourceElement = $doc.CreateElement($Source) + $creds.AppendChild($sourceElement) | Out-Null + } + + # Add the node to the credential if none is found. + $usernameElement = $sourceElement.SelectSingleNode("add[@key='Username']") + if ($usernameElement -eq $null) + { + $usernameElement = $doc.CreateElement("add") + $usernameElement.SetAttribute("key", "Username") + $sourceElement.AppendChild($usernameElement) | Out-Null + } + $usernameElement.SetAttribute("value", $Username) + + # Add the to the credential if none is found. + # Add it as a clear text because there is no support for encrypted ones in non-windows .Net SDKs. + # -> https://github.com/NuGet/Home/issues/5526 + $passwordElement = $sourceElement.SelectSingleNode("add[@key='ClearTextPassword']") + if ($passwordElement -eq $null) + { + $passwordElement = $doc.CreateElement("add") + $passwordElement.SetAttribute("key", "ClearTextPassword") + $sourceElement.AppendChild($passwordElement) | Out-Null + } + $passwordElement.SetAttribute("value", $Password) +} + +function InsertMaestroPrivateFeedCredentials($Sources, $Creds, $Password) { + $maestroPrivateSources = $Sources.SelectNodes("add[contains(@key,'darc-int')]") + + Write-Host "Inserting credentials for $($maestroPrivateSources.Count) Maestro's private feeds." + + ForEach ($PackageSource in $maestroPrivateSources) { + Write-Host "`tInserting credential for Maestro's feed:" $PackageSource.Key + AddCredential -Creds $creds -Source $PackageSource.Key -Username $Username -Password $Password + } +} + +if (!(Test-Path $ConfigFile -PathType Leaf)) { + Write-Host "Couldn't find the file NuGet config file: $ConfigFile" + ExitWithExitCode 1 +} + +# Load NuGet.config +$doc = New-Object System.Xml.XmlDocument +$filename = (Get-Item $ConfigFile).FullName +$doc.Load($filename) + +# Get reference to or create one if none exist already +$sources = $doc.DocumentElement.SelectSingleNode("packageSources") +if ($sources -eq $null) { + $sources = $doc.CreateElement("packageSources") + $doc.DocumentElement.AppendChild($sources) | Out-Null +} + +# Looks for a node. Create it if none is found. +$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials") +if ($creds -eq $null) { + $creds = $doc.CreateElement("packageSourceCredentials") + $doc.DocumentElement.AppendChild($creds) | Out-Null +} + +# Insert credential nodes for Maestro's private feeds +InsertMaestroPrivateFeedCredentials -Sources $sources -Creds $creds -Password $Password + +AddPackageSource -Sources $sources -SourceName "dotnet3-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password +AddPackageSource -Sources $sources -SourceName "dotnet3-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password + +$doc.Save($filename) diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh new file mode 100644 index 000000000000..126452131710 --- /dev/null +++ b/eng/common/SetupNugetSources.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. +# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# +# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry +# under for each Maestro's managed private feed. Two additional credential +# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. +# +# This script needs to be called in every job that will restore packages and which the base repo has +# private AzDO feeds in the NuGet.config. +# +# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` +# from the AzureDevOps-Artifact-Feeds-Pats variable group. +# +# - task: Bash@3 +# displayName: Setup Private Feeds Credentials +# inputs: +# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh +# arguments: $BUILD_SOURCESDIRECTORY/NuGet.config $Token +# condition: ne(variables['Agent.OS'], 'Windows_NT') +# env: +# Token: $(dn-bot-dnceng-artifact-feeds-rw) + +ConfigFile=$1 +CredToken=$2 +NL='\n' +TB=' ' + +source="${BASH_SOURCE[0]}" + +# resolve $source until the file is no longer a symlink +while [[ -h "$source" ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" +done +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + +. "$scriptroot/tools.sh" + +if [ ! -f "$ConfigFile" ]; then + echo "Couldn't find the file NuGet config file: $ConfigFile" + ExitWithExitCode 1 +fi + +if [[ `uname -s` == "Darwin" ]]; then + NL=$'\\\n' + TB='' +fi + +# Ensure there is a ... section. +grep -i "" $ConfigFile +if [ "$?" != "0" ]; then + echo "Adding ... section." + ConfigNodeHeader="" + PackageSourcesTemplate="${TB}${NL}${TB}" + + sed -i.bak "s|$ConfigNodeHeader|$ConfigNodeHeader${NL}$PackageSourcesTemplate|" NuGet.config +fi + +# Ensure there is a ... section. +grep -i "" $ConfigFile +if [ "$?" != "0" ]; then + echo "Adding ... section." + + PackageSourcesNodeFooter="" + PackageSourceCredentialsTemplate="${TB}${NL}${TB}" + + sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourcesNodeFooter${NL}$PackageSourceCredentialsTemplate|" NuGet.config +fi + +# Ensure dotnet3-internal and dotnet3-internal-transport is in the packageSources +grep -i "" $ConfigFile +if [ "$?" != "0" ]; then + echo "Adding dotnet3-internal to the packageSources." + + PackageSourcesNodeFooter="" + PackageSourceTemplate="${TB}" + + sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" NuGet.config +fi + +# Ensure dotnet3-internal and dotnet3-internal-transport is in the packageSources +grep -i "" $ConfigFile +if [ "$?" != "0" ]; then + echo "Adding dotnet3-internal-transport to the packageSources." + + PackageSourcesNodeFooter="" + PackageSourceTemplate="${TB}" + + sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" NuGet.config +fi + +# I want things split line by line +PrevIFS=$IFS +IFS=$'\n' +PackageSources=$(grep -oh '"darc-int-[^"]*"' $ConfigFile | tr -d '"') +IFS=$PrevIFS + +PackageSources+=('dotnet3-internal') +PackageSources+=('dotnet3-internal-transport') + +for FeedName in ${PackageSources[@]} ; do + # Check if there is no existing credential for this FeedName + grep -i "<$FeedName>" $ConfigFile + if [ "$?" != "0" ]; then + echo "Adding credentials for $FeedName." + + PackageSourceCredentialsNodeFooter="" + NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}" + + sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" NuGet.config + fi +done diff --git a/global.json b/global.json index f8f800baef37..13a042781ee7 100644 --- a/global.json +++ b/global.json @@ -25,7 +25,7 @@ }, "msbuild-sdks": { "Yarn.MSBuild": "1.15.2", - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19572.3", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19572.3" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19577.5", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19577.5" } } From 76ae0a2e217a290677418838db90c9173d555d61 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 3 Dec 2019 13:47:33 -0800 Subject: [PATCH 028/322] Build fewer things in blazor-wasm (#17533) --- .azure/pipelines/ci.yml | 358 +----------------- eng/Build.props | 5 + .../test/BlazorServerTemplateTest.cs | 168 -------- .../test/EmptyWebTemplateTest.cs | 73 ---- src/ProjectTemplates/test/GrpcTemplateTest.cs | 89 ----- .../test/IdentityUIPackageTest.cs | 190 ---------- .../ItemTemplateTests/BlazorServerTests.cs | 36 -- src/ProjectTemplates/test/MvcTemplateTest.cs | 216 ----------- .../test/RazorClassLibraryTemplateTest.cs | 62 --- .../test/RazorPagesTemplateTest.cs | 222 ----------- .../SpaTemplateTest/AngularTemplateTest.cs | 30 -- .../SpaTemplateTest/ReactReduxTemplateTest.cs | 23 -- .../test/SpaTemplateTest/ReactTemplateTest.cs | 32 -- .../SpaTemplateTest/SpaTemplateTestBase.cs | 339 ----------------- .../test/WebApiTemplateTest.cs | 70 ---- .../test/WorkerTemplateTest.cs | 56 --- 16 files changed, 7 insertions(+), 1962 deletions(-) delete mode 100644 src/ProjectTemplates/test/BlazorServerTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/EmptyWebTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/GrpcTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/IdentityUIPackageTest.cs delete mode 100644 src/ProjectTemplates/test/ItemTemplateTests/BlazorServerTests.cs delete mode 100644 src/ProjectTemplates/test/MvcTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/RazorPagesTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs delete mode 100644 src/ProjectTemplates/test/WebApiTemplateTest.cs delete mode 100644 src/ProjectTemplates/test/WorkerTemplateTest.cs diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 2d9fa95fb48c..926e0b934a5d 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -69,26 +69,11 @@ variables: # used for post-build phases, internal builds only - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: DotNet-AspNet-SDLValidation-Params - + stages: - stage: build displayName: Build jobs: - # Code check - - template: jobs/default-build.yml - parameters: - jobName: Code_check - jobDisplayName: Code check - agentOs: Windows - steps: - - powershell: ./eng/scripts/CodeCheck.ps1 -ci - displayName: Run eng/scripts/CodeCheck.ps1 - artifacts: - - name: Code_Check_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - # Build Windows (x64/x86) - template: jobs/default-build.yml parameters: @@ -114,34 +99,11 @@ stages: -arch x64 -pack -all - -buildNative + -NoBuildNative /bl:artifacts/log/build.x64.binlog $(_BuildArgs) displayName: Build x64 - # Build the x86 shared framework - # TODO: make it possible to build for one Windows architecture at a time - # This is going to actually build x86 native assets. See https://github.com/aspnet/AspNetCore/issues/7196 - - script: ./build.cmd - -ci - -arch x86 - -pack - -all - -buildNative - -noBuildJava - /p:OnlyPackPlatformSpecificPackages=true - /bl:artifacts/log/build.x86.binlog - $(_BuildArgs) - displayName: Build x86 - - # This is in a separate build step with -forceCoreMsbuild to workaround MAX_PATH limitations - https://github.com/Microsoft/msbuild/issues/53 - - script: .\src\SiteExtensions\build.cmd - -ci - -pack - -noBuildDeps - $(_BuildArgs) - displayName: Build SiteExtension - # This runs code-signing on all packages, zips, and jar files as defined in build/CodeSign.targets. If https://github.com/dotnet/arcade/issues/1957 is resolved, # consider running code-signing inline with the other previous steps. # Sign check is disabled because it is run in a separate step below, after installers are built. @@ -155,29 +117,6 @@ stages: $(_BuildArgs) displayName: Code sign packages - # Windows installers bundle both x86 and x64 assets - - script: ./build.cmd - -ci - -sign - -buildInstallers - /bl:artifacts/log/installers.msbuild.binlog - /p:DotNetSignType=$(_SignType) - /p:AssetManifestFileName=aspnetcore-win-x64-x86.xml - $(_BuildArgs) - $(_PublishArgs) - /p:PublishInstallerBaseVersion=true - displayName: Build Installers - - # A few files must also go to the VS package feed. - - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: NuGetCommand@2 - displayName: Push Visual Studio packages - inputs: - command: push - packagesToPush: 'artifacts/packages/**/VS.Redist.Common.AspNetCore.*.nupkg' - nuGetFeedType: external - publishFeedCredentials: 'DevDiv - VS package feed' - artifacts: - name: Windows_Logs path: artifacts/log/ @@ -186,251 +125,6 @@ stages: - name: Windows_Packages path: artifacts/packages/ - # Build Windows ARM - - template: jobs/default-build.yml - parameters: - codeSign: true - jobName: Windows_arm_build - jobDisplayName: "Build: Windows ARM" - agentOs: Windows - buildArgs: - -arch arm - -sign - -pack - -noBuildNodeJS - -noBuildJava - /bl:artifacts/log/build.win-arm.binlog - /p:DotNetSignType=$(_SignType) - /p:OnlyPackPlatformSpecificPackages=true - /p:AssetManifestFileName=aspnetcore-win-arm.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: Windows_arm_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Windows_arm_Packages - path: artifacts/packages/ - - # Build MacOS - - template: jobs/default-build.yml - parameters: - jobName: MacOs_x64_build - jobDisplayName: "Build: macOS" - agentOs: macOs - buildArgs: - --pack - --all - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.macos.binlog - -p:AssetManifestFileName=aspnetcore-MacOS_x64.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: MacOS_x64_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: MacOS_x64_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: MacOS_x64 - - # Build Linux x64 - - template: jobs/default-build.yml - parameters: - jobName: Linux_x64_build - jobDisplayName: "Build: Linux x64" - agentOs: Linux - steps: - - script: ./build.sh - --ci - --arch x64 - --pack - --all - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.linux-x64.binlog - $(_BuildArgs) - displayName: Run build.sh - - script: | - git clean -xfd src/**/obj/ - ./dockerbuild.sh bionic \ - --ci \ - --arch x64 \ - --build-installers \ - --no-build-deps \ - --no-build-nodejs \ - -p:OnlyPackPlatformSpecificPackages=true \ - -p:BuildRuntimeArchive=false \ - -p:LinuxInstallerType=deb \ - -bl:artifacts/log/build.deb.binlog \ - $(_BuildArgs) - displayName: Build Debian installers - - script: | - git clean -xfd src/**/obj/ - ./dockerbuild.sh rhel \ - --ci \ - --arch x64 \ - --build-installers \ - --no-build-deps \ - --no-build-nodejs \ - -p:OnlyPackPlatformSpecificPackages=true \ - -p:BuildRuntimeArchive=false \ - -p:LinuxInstallerType=rpm \ - -bl:artifacts/log/build.rpm.binlog \ - -p:AssetManifestFileName=aspnetcore-Linux_x64.xml \ - $(_BuildArgs) \ - $(_PublishArgs) - displayName: Build RPM installers - installNodeJs: false - installJdk: false - artifacts: - - name: Linux_x64_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_x64_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: Linux_x64 - - # Build Linux ARM - - template: jobs/default-build.yml - parameters: - jobName: Linux_arm_build - jobDisplayName: "Build: Linux ARM" - agentOs: Linux - buildArgs: - --arch arm - --pack - --all - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.linux-arm.binlog - -p:AssetManifestFileName=aspnetcore-Linux_arm.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: Linux_arm_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_arm_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: Linux_arm - - # Build Linux ARM64 - - template: jobs/default-build.yml - parameters: - jobName: Linux_arm64_build - jobDisplayName: "Build: Linux ARM64" - agentOs: Linux - buildArgs: - --arch arm64 - --all - --pack - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.arm64.binlog - -p:AssetManifestFileName=aspnetcore-Linux_arm64.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: Linux_arm64_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_arm64_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: Linux_arm64 - - # Build Linux Musl x64 - - template: jobs/default-build.yml - parameters: - jobName: Linux_musl_x64_build - jobDisplayName: "Build: Linux Musl x64" - agentOs: Linux - buildScript: ./dockerbuild.sh alpine - buildArgs: - --ci - --arch x64 - --os-name linux-musl - --pack - --all - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.musl.binlog - -p:AssetManifestFileName=aspnetcore-Linux_musl_x64.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: Linux_musl_x64_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_musl_x64_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: Linux_musl_x64 - - # Build Linux Musl ARM64 - - template: jobs/default-build.yml - parameters: - jobName: Linux_musl_arm64_build - jobDisplayName: "Build: Linux Musl ARM64" - agentOs: Linux - buildScript: ./dockerbuild.sh ubuntu-alpine37 - buildArgs: - --ci - --arch arm64 - --os-name linux-musl - --pack - --all - --no-build-nodejs - --no-build-java - -p:OnlyPackPlatformSpecificPackages=true - -bl:artifacts/log/build.musl.binlog - -p:AssetManifestFileName=aspnetcore-Linux_musl_arm64.xml - $(_BuildArgs) - $(_PublishArgs) - installNodeJs: false - installJdk: false - artifacts: - - name: Linux_musl_arm64_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_musl_arm64_Packages - path: artifacts/packages/ - - template: jobs/codesign-xplat.yml - parameters: - inputName: Linux_musl_arm64 - # Test jobs - template: jobs/default-build.yml parameters: @@ -567,63 +261,15 @@ stages: publishOnError: true includeForks: true - # Source build - - job: Source_Build - displayName: 'Test: Linux Source Build' - container: centos:7 - pool: - vmImage: 'ubuntu-16.04' - variables: - DotNetCoreSdkDir: $(Agent.ToolsDirectory)/dotnet - DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: true - steps: - - script: | - source eng/common/native/common-library.sh - mkdir -p $HOME/bin - GetFile https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 $HOME/bin/jq - chmod +x $HOME/bin/jq - echo "##vso[task.prependpath]$HOME/bin" - displayName: Install jq - - script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true /p:BuildNodeJs=false - displayName: Run ci-source-build.sh - - task: PublishBuildArtifacts@1 - displayName: Upload logs - condition: always() - continueOnError: true - inputs: - pathtoPublish: artifacts/log/ - artifactName: Source_Build_Logs - artifactType: Container - parallel: true - - task: PublishBuildArtifacts@1 - displayName: Upload package artifacts - # Only capture source build artifacts in PRs for the sake of inspecting - # changes that impact source-build. The artifacts from this build pipeline are never actually used. - condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) - inputs: - pathtoPublish: artifacts/packages/ - artifactName: Source_Build_Packages - artifactType: Container - parallel: true - # Publish to the BAR - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - template: /eng/common/templates/job/publish-build-assets.yml parameters: dependsOn: - Windows_build - - Windows_arm_build - - CodeSign_Xplat_MacOS_x64 - - CodeSign_Xplat_Linux_x64 - - CodeSign_Xplat_Linux_arm - - CodeSign_Xplat_Linux_arm64 - - CodeSign_Xplat_Linux_musl_x64 - - CodeSign_Xplat_Linux_musl_arm64 # In addition to the dependencies above, ensure the build was successful overall. - - Code_check - Linux_Test - MacOS_Test - - Source_Build - Windows_Templates_Test - Windows_Test pool: diff --git a/eng/Build.props b/eng/Build.props index f8a3b7027abf..3378e22c3978 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -50,6 +50,11 @@ " /> + + + $(RepoRoot)src\Components\**\*.csproj;$(RepoRoot)src\ProjectTemplates\**\*.csproj + + diff --git a/src/ProjectTemplates/test/BlazorServerTemplateTest.cs b/src/ProjectTemplates/test/BlazorServerTemplateTest.cs deleted file mode 100644 index 463b710ac35b..000000000000 --- a/src/ProjectTemplates/test/BlazorServerTemplateTest.cs +++ /dev/null @@ -1,168 +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.Net; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.E2ETesting; -using Microsoft.AspNetCore.Testing; -using OpenQA.Selenium; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class BlazorServerTemplateTest : BrowserTestBase - { - public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) : base(browserFixture, output) - { - ProjectFactory = projectFactory; - } - - public ProjectFactoryFixture ProjectFactory { get; set; } - - public Project Project { get; private set; } - - [Fact] - public async Task BlazorServerTemplateWorks_NoAuth() - { - Project = await ProjectFactory.GetOrCreateProject("blazorservernoauth", Output); - - var createResult = await Project.RunDotNetNewAsync("blazorserver"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - if (BrowserFixture.IsHostAutomationSupported()) - { - aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - if (BrowserFixture.IsHostAutomationSupported()) - { - aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task BlazorServerTemplateWorks_IndividualAuth(bool useLocalDB) - { - Project = await ProjectFactory.GetOrCreateProject("blazorserverindividual" + (useLocalDB ? "uld" : ""), Output); - - var createResult = await Project.RunDotNetNewAsync("blazorserver", auth: "Individual", useLocalDB: useLocalDB); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - if (BrowserFixture.IsHostAutomationSupported()) - { - aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - if (BrowserFixture.IsHostAutomationSupported()) - { - aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(); - } - } - } - - private void TestBasicNavigation() - { - // Give components.server enough time to load so that it can replace - // the prerendered content before we start making assertions. - Thread.Sleep(5000); - Browser.Exists(By.TagName("ul")); - // element gets project ID injected into it during template execution - Browser.Equal(Project.ProjectName.Trim(), () => Browser.Title.Trim()); - - // Initially displays the home page - Browser.Equal("Hello, world!", () => Browser.FindElement(By.TagName("h1")).Text); - - // Can navigate to the counter page - Browser.FindElement(By.PartialLinkText("Counter")).Click(); - Browser.Contains("counter", () => Browser.Url); - Browser.Equal("Counter", () => Browser.FindElement(By.TagName("h1")).Text); - - // Clicking the counter button works - Browser.Equal("Current count: 0", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); - Browser.FindElement(By.CssSelector("p+button")).Click(); - Browser.Equal("Current count: 1", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); - - // Can navigate to the 'fetch data' page - Browser.FindElement(By.PartialLinkText("Fetch data")).Click(); - Browser.Contains("fetchdata", () => Browser.Url); - Browser.Equal("Weather forecast", () => Browser.FindElement(By.TagName("h1")).Text); - - // Asynchronously loads and displays the table of weather forecasts - Browser.Exists(By.CssSelector("table>tbody>tr")); - Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count); - } - } -} diff --git a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs b/src/ProjectTemplates/test/EmptyWebTemplateTest.cs deleted file mode 100644 index 56e2e8c10539..000000000000 --- a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs +++ /dev/null @@ -1,73 +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.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class EmptyWebTemplateTest - { - public EmptyWebTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; } - - public ITestOutputHelper Output { get; } - - [Fact] - public async Task EmptyWebTemplateCSharp() - { - await EmtpyTemplateCore(languageOverride: null); - } - - [Fact] - public async Task EmptyWebTemplateFSharp() - { - await EmtpyTemplateCore("F#"); - } - - private async Task EmtpyTemplateCore(string languageOverride) - { - Project = await ProjectFactory.GetOrCreateProject("empty" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output); - - var createResult = await Project.RunDotNetNewAsync("web", language: languageOverride); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertOk("/"); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertOk("/"); - } - } - } -} diff --git a/src/ProjectTemplates/test/GrpcTemplateTest.cs b/src/ProjectTemplates/test/GrpcTemplateTest.cs deleted file mode 100644 index 4713a7a9c454..000000000000 --- a/src/ProjectTemplates/test/GrpcTemplateTest.cs +++ /dev/null @@ -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.Runtime.InteropServices; -using System.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class GrpcTemplateTest - { - public GrpcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; } - public ITestOutputHelper Output { get; } - - [Fact] - public async Task GrpcTemplate() - { - Project = await ProjectFactory.GetOrCreateProject("grpc", Output); - - var createResult = await Project.RunDotNetNewAsync("grpc"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var serverProcess = Project.StartBuiltProjectAsync()) - { - // These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support. - // https://github.com/aspnet/AspNetCore/issues/11061 - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - Assert.True(serverProcess.Process.HasExited, "built"); - Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.", - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version < new Version(6, 2)) - { - Assert.True(serverProcess.Process.HasExited, "built"); - Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.", - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); - } - else - { - Assert.False( - serverProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); - } - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - // These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support. - // https://github.com/aspnet/AspNetCore/issues/11061 - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - Assert.True(aspNetProcess.Process.HasExited, "published"); - Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.", - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version < new Version(6, 2)) - { - Assert.True(aspNetProcess.Process.HasExited, "published"); - Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.", - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); - } - else - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); - } - } - } - } -} diff --git a/src/ProjectTemplates/test/IdentityUIPackageTest.cs b/src/ProjectTemplates/test/IdentityUIPackageTest.cs deleted file mode 100644 index deede64521a5..000000000000 --- a/src/ProjectTemplates/test/IdentityUIPackageTest.cs +++ /dev/null @@ -1,190 +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.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class IdentityUIPackageTest - { - public IdentityUIPackageTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; set; } - - public ITestOutputHelper Output { get; } - - public static TheoryData<IDictionary<string, string>, string, string[]> MSBuildIdentityUIPackageOptions - { - get - { - var data = new TheoryData<IDictionary<string, string>, string, string[]>(); - - data.Add(new Dictionary<string, string> - { - ["IdentityUIFrameworkVersion"] = "Bootstrap3" - }, - "Bootstrap v3.4.1", - Bootstrap3ContentFiles); - - data.Add(new Dictionary<string, string>(), "Bootstrap v4.3.1", Bootstrap4ContentFiles); - - return data; - } - } - - public static string[] Bootstrap3ContentFiles { get; } = new string[] - { - "Identity/css/site.css", - "Identity/js/site.js", - "Identity/lib/bootstrap/dist/css/bootstrap-theme.css", - "Identity/lib/bootstrap/dist/css/bootstrap-theme.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap-theme.min.css", - "Identity/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap.css", - "Identity/lib/bootstrap/dist/css/bootstrap.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap.min.css", - "Identity/lib/bootstrap/dist/css/bootstrap.min.css.map", - "Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", - "Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", - "Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", - "Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", - "Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", - "Identity/lib/bootstrap/dist/js/bootstrap.js", - "Identity/lib/bootstrap/dist/js/bootstrap.min.js", - "Identity/lib/bootstrap/dist/js/npm.js", - "Identity/lib/jquery/LICENSE.txt", - "Identity/lib/jquery/dist/jquery.js", - "Identity/lib/jquery/dist/jquery.min.js", - "Identity/lib/jquery/dist/jquery.min.map", - "Identity/lib/jquery-validation/LICENSE.md", - "Identity/lib/jquery-validation/dist/additional-methods.js", - "Identity/lib/jquery-validation/dist/additional-methods.min.js", - "Identity/lib/jquery-validation/dist/jquery.validate.js", - "Identity/lib/jquery-validation/dist/jquery.validate.min.js", - "Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", - "Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js", - "Identity/lib/jquery-validation-unobtrusive/LICENSE.txt", - }; - - public static string[] Bootstrap4ContentFiles { get; } = new string[] - { - "Identity/favicon.ico", - "Identity/css/site.css", - "Identity/js/site.js", - "Identity/lib/bootstrap/dist/css/bootstrap-grid.css", - "Identity/lib/bootstrap/dist/css/bootstrap-grid.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap-grid.min.css", - "Identity/lib/bootstrap/dist/css/bootstrap-grid.min.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap-reboot.css", - "Identity/lib/bootstrap/dist/css/bootstrap-reboot.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap-reboot.min.css", - "Identity/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap.css", - "Identity/lib/bootstrap/dist/css/bootstrap.css.map", - "Identity/lib/bootstrap/dist/css/bootstrap.min.css", - "Identity/lib/bootstrap/dist/css/bootstrap.min.css.map", - "Identity/lib/bootstrap/dist/js/bootstrap.bundle.js", - "Identity/lib/bootstrap/dist/js/bootstrap.bundle.js.map", - "Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js", - "Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map", - "Identity/lib/bootstrap/dist/js/bootstrap.js", - "Identity/lib/bootstrap/dist/js/bootstrap.js.map", - "Identity/lib/bootstrap/dist/js/bootstrap.min.js", - "Identity/lib/bootstrap/dist/js/bootstrap.min.js.map", - "Identity/lib/jquery/LICENSE.txt", - "Identity/lib/jquery/dist/jquery.js", - "Identity/lib/jquery/dist/jquery.min.js", - "Identity/lib/jquery/dist/jquery.min.map", - "Identity/lib/jquery-validation/LICENSE.md", - "Identity/lib/jquery-validation/dist/additional-methods.js", - "Identity/lib/jquery-validation/dist/additional-methods.min.js", - "Identity/lib/jquery-validation/dist/jquery.validate.js", - "Identity/lib/jquery-validation/dist/jquery.validate.min.js", - "Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", - "Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js", - "Identity/lib/jquery-validation-unobtrusive/LICENSE.txt", - }; - - [Theory] - [MemberData(nameof(MSBuildIdentityUIPackageOptions))] - public async Task IdentityUIPackage_WorksWithDifferentOptions(IDictionary<string, string> packageOptions, string versionValidator, string[] expectedFiles) - { - Project = await ProjectFactory.GetOrCreateProject("identityuipackage" + string.Concat(packageOptions.Values), Output); - var useLocalDB = false; - - var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); - Assert.Contains(".db", projectFileContents); - - var publishResult = await Project.RunDotNetPublishAsync(packageOptions: packageOptions); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(packageOptions: packageOptions); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages"); - Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); - Project.AssertEmptyMigration("razorpages"); - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains(versionValidator, await response.Content.ReadAsStringAsync()); - await ValidatePublishedFiles(aspNetProcess, expectedFiles); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains(versionValidator, await response.Content.ReadAsStringAsync()); - await ValidatePublishedFiles(aspNetProcess, expectedFiles); - } - } - - private async Task ValidatePublishedFiles(AspNetProcess aspNetProcess, string[] expectedContentFiles) - { - foreach (var file in expectedContentFiles) - { - var response = await aspNetProcess.SendRequest(file); - Assert.True(response?.StatusCode == HttpStatusCode.OK, $"Couldn't find file '{file}'"); - } - } - - private string ReadFile(string basePath, string path) - { - var fullPath = Path.Combine(basePath, path); - var doesExist = File.Exists(fullPath); - - Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}"); - return File.ReadAllText(Path.Combine(basePath, path)); - } - } -} diff --git a/src/ProjectTemplates/test/ItemTemplateTests/BlazorServerTests.cs b/src/ProjectTemplates/test/ItemTemplateTests/BlazorServerTests.cs deleted file mode 100644 index 842ce8a5d9a8..000000000000 --- a/src/ProjectTemplates/test/ItemTemplateTests/BlazorServerTests.cs +++ /dev/null @@ -1,36 +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.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Items.Test -{ - public class BlazorServerTest - { - public BlazorServerTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; } - public ITestOutputHelper Output { get; } - - [Fact] - public async Task BlazorServerItemTemplate() - { - Project = await ProjectFactory.GetOrCreateProject("razorcomponentitem", Output); - - var createResult = await Project.RunDotNetNewAsync("razorcomponent --name Different"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create", Project, createResult)); - - Project.AssertFileExists("Different.razor", shouldExist: true); - Assert.Contains("<h3>Different</h3>", Project.ReadFile("Different.razor")); - } - } -} diff --git a/src/ProjectTemplates/test/MvcTemplateTest.cs b/src/ProjectTemplates/test/MvcTemplateTest.cs deleted file mode 100644 index af43914ed26b..000000000000 --- a/src/ProjectTemplates/test/MvcTemplateTest.cs +++ /dev/null @@ -1,216 +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.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Templates.Test.Helpers; -using System.Linq; -using Xunit; -using Xunit.Abstractions; -using Microsoft.AspNetCore.Testing; - -namespace Templates.Test -{ - public class MvcTemplateTest - { - public MvcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; } - public ITestOutputHelper Output { get; } - - [Fact] - public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#"); - - [Fact] - public async Task MvcTemplate_NoAuthCSharp() => await MvcTemplateCore(languageOverride: null); - - private async Task MvcTemplateCore(string languageOverride) - { - Project = await ProjectFactory.GetOrCreateProject("mvcnoauth" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output); - - var createResult = await Project.RunDotNetNewAsync("mvc", language: languageOverride); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var projectExtension = languageOverride == "F#" ? "fsproj" : "csproj"; - var projectFileContents = Project.ReadFile($"{Project.ProjectName}.{projectExtension}"); - Assert.DoesNotContain(".db", projectFileContents); - Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents); - Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); - Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents); - Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - IEnumerable<string> menuLinks = new List<string> { - PageUrls.HomeUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyFullUrl - }; - - var footerLinks = new string[] { PageUrls.PrivacyFullUrl }; - - var pages = new List<Page> - { - new Page - { - Url = PageUrls.HomeUrl, - Links = menuLinks.Append(PageUrls.DocsUrl).Concat(footerLinks) - }, - new Page - { - Url = PageUrls.PrivacyFullUrl, - Links = menuLinks.Concat(footerLinks) - } - }; - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task MvcTemplate_IndividualAuth(bool useLocalDB) - { - Project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output); - - var createResult = await Project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: useLocalDB); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var projectFileContents = Project.ReadFile($"{Project.ProjectName}.csproj"); - if (!useLocalDB) - { - Assert.Contains(".db", projectFileContents); - } - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("mvc"); - Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); - Project.AssertEmptyMigration("mvc"); - - var pages = new List<Page> { - new Page - { - Url = PageUrls.ForgotPassword, - Links = new string [] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.HomeUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.DocsUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.PrivacyFullUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.LoginUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.ForgotPassword, - PageUrls.RegisterUrl, - PageUrls.ExternalArticle, - PageUrls.PrivacyUrl } - }, - new Page - { - Url = PageUrls.RegisterUrl, - Links = new string [] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.ExternalArticle, - PageUrls.PrivacyUrl - } - } - }; - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - } - } -} diff --git a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs deleted file mode 100644 index 0d02a56f8f84..000000000000 --- a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs +++ /dev/null @@ -1,62 +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.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class RazorClassLibraryTemplateTest - { - public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; } - public ITestOutputHelper Output { get; } - - [Fact] - public async Task RazorClassLibraryTemplate_WithViews_Async() - { - Project = await ProjectFactory.GetOrCreateProject("razorclasslibwithviews", Output); - - var createResult = await Project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" }); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - } - - [Fact] - public async Task RazorClassLibraryTemplateAsync() - { - Project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output); - - var createResult = await Project.RunDotNetNewAsync("razorclasslib"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - } - } -} diff --git a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs b/src/ProjectTemplates/test/RazorPagesTemplateTest.cs deleted file mode 100644 index 7cd41d56b26e..000000000000 --- a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs +++ /dev/null @@ -1,222 +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.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class RazorPagesTemplateTest - { - public RazorPagesTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - - public ProjectFactoryFixture ProjectFactory { get; set; } - - public ITestOutputHelper Output { get; } - - [Fact] - public async Task RazorPagesTemplate_NoAuth() - { - Project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output); - - var createResult = await Project.RunDotNetNewAsync("razor"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("razor", Project, createResult)); - - var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); - Assert.DoesNotContain(".db", projectFileContents); - Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents); - Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); - Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents); - Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, createResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, createResult)); - - var pages = new List<Page> - { - new Page - { - Url = PageUrls.HomeUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.DocsUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.PrivacyUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.PrivacyUrl } - } - }; - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) - { - Project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output); - - var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); - if (!useLocalDB) - { - Assert.Contains(".db", projectFileContents); - } - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages"); - Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); - Project.AssertEmptyMigration("razorpages"); - - var pages = new List<Page> { - new Page - { - Url = PageUrls.ForgotPassword, - Links = new string [] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.HomeUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.DocsUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.PrivacyUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.PrivacyUrl - } - }, - new Page - { - Url = PageUrls.LoginUrl, - Links = new string[] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.ForgotPassword, - PageUrls.RegisterUrl, - PageUrls.ExternalArticle, - PageUrls.PrivacyUrl } - }, - new Page - { - Url = PageUrls.RegisterUrl, - Links = new string [] { - PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, - PageUrls.HomeUrl, - PageUrls.PrivacyUrl, - PageUrls.ExternalArticle, - PageUrls.PrivacyUrl - } - } - }; - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertPagesOk(pages); - } - } - - - private string ReadFile(string basePath, string path) - { - var fullPath = Path.Combine(basePath, path); - var doesExist = File.Exists(fullPath); - - Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}"); - return File.ReadAllText(Path.Combine(basePath, path)); - } - } -} diff --git a/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs deleted file mode 100644 index e1d5db13388e..000000000000 --- a/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs +++ /dev/null @@ -1,30 +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.Threading.Tasks; -using Microsoft.AspNetCore.E2ETesting; -using Microsoft.AspNetCore.Testing; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test.SpaTemplateTest -{ - public class AngularTemplateTest : SpaTemplateTestBase - { - public AngularTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) - : base(projectFactory, browserFixture, output) { } - - [Fact] - public Task AngularTemplate_Works() - => SpaTemplateImplAsync("angularnoauth", "angular", useLocalDb: false, usesAuth: false); - - [Fact] - public Task AngularTemplate_IndividualAuth_Works() - => SpaTemplateImplAsync("angularindividual", "angular", useLocalDb: false, usesAuth: true); - - [Fact] - public Task AngularTemplate_IndividualAuth_Works_LocalDb() - => SpaTemplateImplAsync("angularindividualuld", "angular", useLocalDb: true, usesAuth: true); - } -} diff --git a/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs deleted file mode 100644 index 44d6b67f3256..000000000000 --- a/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs +++ /dev/null @@ -1,23 +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.Threading.Tasks; -using Microsoft.AspNetCore.E2ETesting; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test.SpaTemplateTest -{ - public class ReactReduxTemplateTest : SpaTemplateTestBase - { - public ReactReduxTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) - : base(projectFactory, browserFixture, output) - { - } - - [Fact] - public Task ReactReduxTemplate_Works_NetCore() - => SpaTemplateImplAsync("reactredux", "reactredux", useLocalDb: false, usesAuth: false); - } -} diff --git a/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs deleted file mode 100644 index 469e87acd560..000000000000 --- a/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs +++ /dev/null @@ -1,32 +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.Threading.Tasks; -using Microsoft.AspNetCore.E2ETesting; -using Microsoft.AspNetCore.Testing; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test.SpaTemplateTest -{ - public class ReactTemplateTest : SpaTemplateTestBase - { - public ReactTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) - : base(projectFactory, browserFixture, output) - { - } - - [Fact] - public Task ReactTemplate_Works_NetCore() - => SpaTemplateImplAsync("reactnoauth", "react", useLocalDb: false, usesAuth: false); - - [Fact] - public Task ReactTemplate_IndividualAuth_NetCore() - => SpaTemplateImplAsync("reactindividual", "react", useLocalDb: false, usesAuth: true); - - [Fact] - public Task ReactTemplate_IndividualAuth_NetCore_LocalDb() - => SpaTemplateImplAsync("reactindividualuld", "react", useLocalDb: true, usesAuth: true); - } -} diff --git a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs deleted file mode 100644 index fa2c3fb9fa3b..000000000000 --- a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs +++ /dev/null @@ -1,339 +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.Net; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNetCore.E2ETesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -// Turn off parallel test run for Edge as the driver does not support multiple Selenium tests at the same time -#if EDGE -[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] -#endif -namespace Templates.Test.SpaTemplateTest -{ - public class SpaTemplateTestBase : BrowserTestBase - { - public SpaTemplateTestBase( - ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) : base(browserFixture, output) - { - ProjectFactory = projectFactory; - } - - public ProjectFactoryFixture ProjectFactory { get; set; } - - public Project Project { get; set; } - - // Rather than using [Theory] to pass each of the different values for 'template', - // it's important to distribute the SPA template tests over different test classes - // so they can be run in parallel. Xunit doesn't parallelize within a test class. - protected async Task SpaTemplateImplAsync( - string key, - string template, - bool useLocalDb = false, - bool usesAuth = false) - { - Project = await ProjectFactory.GetOrCreateProject(key, Output); - - using var createResult = await Project.RunDotNetNewAsync(template, auth: usesAuth ? "Individual" : null, language: null, useLocalDb); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - // We shouldn't have to do the NPM restore in tests because it should happen - // automatically at build time, but by doing it up front we can avoid having - // multiple NPM installs run concurrently which otherwise causes errors when - // tests run in parallel. - var clientAppSubdirPath = Path.Combine(Project.TemplateOutputDir, "ClientApp"); - ValidatePackageJson(clientAppSubdirPath); - - var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); - if (usesAuth && !useLocalDb) - { - Assert.Contains(".db", projectFileContents); - } - - using var npmRestoreResult = await Project.RestoreWithRetryAsync(Output, clientAppSubdirPath); - Assert.True(0 == npmRestoreResult.ExitCode, ErrorMessages.GetFailedProcessMessage("npm restore", Project, npmRestoreResult)); - - using var lintResult = ProcessEx.RunViaShell(Output, clientAppSubdirPath, "npm run lint"); - Assert.True(0 == lintResult.ExitCode, ErrorMessages.GetFailedProcessMessage("npm run lint", Project, lintResult)); - - // The default behavior of angular tests is watch mode, which leaves the test process open after it finishes, which leads to delays/hangs. - var testcommand = "npm run test" + template == "angular" ? "-- --watch=false" : ""; - - using var testResult = ProcessEx.RunViaShell(Output, clientAppSubdirPath, testcommand); - Assert.True(0 == testResult.ExitCode, ErrorMessages.GetFailedProcessMessage("npm run test", Project, testResult)); - - using var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - using var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - // localdb is not installed on the CI machines, so skip it. - var shouldVisitFetchData = !(useLocalDb && Project.IsCIEnvironment); - - if (usesAuth) - { - using var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync(template); - Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); - Project.AssertEmptyMigration(template); - - if (shouldVisitFetchData) - { - using var dbUpdateResult = await Project.RunDotNetEfUpdateDatabaseAsync(); - Assert.True(0 == dbUpdateResult.ExitCode, ErrorMessages.GetFailedProcessMessage("update database", Project, dbUpdateResult)); - } - } - - if (template == "react" || template == "reactredux") - { - await CleanupReactClientAppBuildFolder(clientAppSubdirPath); - } - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await WarmUpServer(aspNetProcess); - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - - if (BrowserFixture.IsHostAutomationSupported()) - { - var (browser, logs) = await BrowserFixture.GetOrCreateBrowserAsync(Output, $"{Project.ProjectName}.build"); - aspNetProcess.VisitInBrowser(browser); - TestBasicNavigation(visitFetchData: shouldVisitFetchData, usesAuth, browser, logs); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - - if (usesAuth) - { - UpdatePublishedSettings(); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - await WarmUpServer(aspNetProcess); - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - - if (BrowserFixture.IsHostAutomationSupported()) - { - var (browser, logs) = await BrowserFixture.GetOrCreateBrowserAsync(Output, $"{Project.ProjectName}.publish"); - aspNetProcess.VisitInBrowser(browser); - TestBasicNavigation(visitFetchData: shouldVisitFetchData, usesAuth, browser, logs); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - } - - private async Task CleanupReactClientAppBuildFolder(string clientAppSubdirPath) - { - ProcessEx testResult = null; - int? testResultExitCode = null; - for (int i = 0; i < 3; i++) - { - try - { - testResult = ProcessEx.RunViaShell(Output, clientAppSubdirPath, "npx rimraf ./build"); - testResultExitCode = testResult.ExitCode; - if (testResultExitCode == 0) - { - return; - } - } - catch - { - } - finally - { - testResult.Dispose(); - } - - await Task.Delay(3000); - } - - Assert.True(testResultExitCode == 0, ErrorMessages.GetFailedProcessMessage("npx rimraf ./build", Project, testResult)); - } - - private void ValidatePackageJson(string clientAppSubdirPath) - { - Assert.True(File.Exists(Path.Combine(clientAppSubdirPath, "package.json")), "Missing a package.json"); - var packageJson = JObject.Parse(ReadFile(clientAppSubdirPath, "package.json")); - - // NPM package names must match ^(?:@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$ - var packageName = (string)packageJson["name"]; - Regex regex = new Regex("^(?:@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$"); - Assert.True(regex.IsMatch(packageName), "package.json name is invalid format"); - } - - private static async Task WarmUpServer(AspNetProcess aspNetProcess) - { - var attempt = 0; - var maxAttempts = 3; - do - { - try - { - attempt++; - var response = await aspNetProcess.SendRequest("/"); - if (response.StatusCode == HttpStatusCode.OK) - { - break; - } - } - catch (OperationCanceledException) - { - } - catch (HttpRequestException ex) when (ex.Message.StartsWith("The SSL connection could not be established")) - { - } - await Task.Delay(TimeSpan.FromSeconds(5 * attempt)); - } while (attempt < maxAttempts); - } - - private void UpdatePublishedSettings() - { - // Hijack here the config file to use the development key during publish. - var appSettings = JObject.Parse(File.ReadAllText(Path.Combine(Project.TemplateOutputDir, "appsettings.json"))); - var appSettingsDevelopment = JObject.Parse(File.ReadAllText(Path.Combine(Project.TemplateOutputDir, "appsettings.Development.json"))); - ((JObject)appSettings["IdentityServer"]).Merge(appSettingsDevelopment["IdentityServer"]); - ((JObject)appSettings["IdentityServer"]).Merge(new - { - IdentityServer = new - { - Key = new - { - FilePath = "./tempkey.json" - } - } - }); - var testAppSettings = appSettings.ToString(); - File.WriteAllText(Path.Combine(Project.TemplatePublishDir, "appsettings.json"), testAppSettings); - } - - private void TestBasicNavigation(bool visitFetchData, bool usesAuth, IWebDriver browser, ILogs logs) - { - browser.Exists(By.TagName("ul")); - // <title> element gets project ID injected into it during template execution - browser.Contains(Project.ProjectGuid.Replace(".", "._"), () => browser.Title); - - // Initially displays the home page - browser.Equal("Hello, world!", () => browser.FindElement(By.TagName("h1")).Text); - - // Can navigate to the counter page - browser.FindElement(By.PartialLinkText("Counter")).Click(); - browser.Contains("counter", () => browser.Url); - - browser.Equal("Counter", () => browser.FindElement(By.TagName("h1")).Text); - - // Clicking the counter button works - browser.Equal("0", () => browser.FindElement(By.CssSelector("p>strong")).Text); - browser.FindElement(By.CssSelector("p+button")).Click(); - browser.Equal("1", () => browser.FindElement(By.CssSelector("p>strong")).Text); - - if (visitFetchData) - { - browser.FindElement(By.PartialLinkText("Fetch data")).Click(); - - if (usesAuth) - { - // We will be redirected to the identity UI - browser.Contains("/Identity/Account/Login", () => browser.Url); - browser.FindElement(By.PartialLinkText("Register as a new user")).Click(); - - var userName = $"{Guid.NewGuid()}@example.com"; - var password = $"!Test.Password1$"; - browser.Exists(By.Name("Input.Email")); - browser.FindElement(By.Name("Input.Email")).SendKeys(userName); - browser.FindElement(By.Name("Input.Password")).SendKeys(password); - browser.FindElement(By.Name("Input.ConfirmPassword")).SendKeys(password); - browser.FindElement(By.Id("registerSubmit")).Click(); - - // We will be redirected to the RegisterConfirmation - browser.Contains("/Identity/Account/RegisterConfirmation", () => browser.Url); - browser.FindElement(By.PartialLinkText("Click here to confirm your account")).Click(); - - // We will be redirected to the ConfirmEmail - browser.Contains("/Identity/Account/ConfirmEmail", () => browser.Url); - - // Now we can login - browser.FindElement(By.PartialLinkText("Login")).Click(); - browser.Exists(By.Name("Input.Email")); - browser.FindElement(By.Name("Input.Email")).SendKeys(userName); - browser.FindElement(By.Name("Input.Password")).SendKeys(password); - browser.FindElement(By.Id("login-submit")).Click(); - - // Need to navigate to fetch page - browser.FindElement(By.PartialLinkText("Fetch data")).Click(); - } - - // Can navigate to the 'fetch data' page - browser.Contains("fetch-data", () => browser.Url); - browser.Equal("Weather forecast", () => browser.FindElement(By.TagName("h1")).Text); - - // Asynchronously loads and displays the table of weather forecasts - browser.Exists(By.CssSelector("table>tbody>tr")); - browser.Equal(5, () => browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count); - } - - foreach (var logKind in logs.AvailableLogTypes) - { - var entries = logs.GetLog(logKind); - var badEntries = entries.Where(e => new LogLevel[] { LogLevel.Warning, LogLevel.Severe }.Contains(e.Level)); - - badEntries = badEntries.Where(e => - !e.Message.Contains("failed: WebSocket is closed before the connection is established.") - && !e.Message.Contains("[WDS] Disconnected!") - && !e.Message.Contains("Timed out connecting to Chrome, retrying")); - - Assert.True(badEntries.Count() == 0, "There were Warnings or Errors from the browser." + Environment.NewLine + string.Join(Environment.NewLine, badEntries)); - } - } - - private void AssertFileExists(string basePath, string path, bool shouldExist) - { - var fullPath = Path.Combine(basePath, path); - var doesExist = File.Exists(fullPath); - - if (shouldExist) - { - Assert.True(doesExist, "Expected file to exist, but it doesn't: " + path); - } - else - { - Assert.False(doesExist, "Expected file not to exist, but it does: " + path); - } - } - - private string ReadFile(string basePath, string path) - { - AssertFileExists(basePath, path, shouldExist: true); - return File.ReadAllText(Path.Combine(basePath, path)); - } - } -} diff --git a/src/ProjectTemplates/test/WebApiTemplateTest.cs b/src/ProjectTemplates/test/WebApiTemplateTest.cs deleted file mode 100644 index 89d047a06e63..000000000000 --- a/src/ProjectTemplates/test/WebApiTemplateTest.cs +++ /dev/null @@ -1,70 +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.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class WebApiTemplateTest - { - public WebApiTemplateTest(ProjectFactoryFixture factoryFixture, ITestOutputHelper output) - { - FactoryFixture = factoryFixture; - Output = output; - } - - public ProjectFactoryFixture FactoryFixture { get; } - - public ITestOutputHelper Output { get; } - - public Project Project { get; set; } - - [Fact] - public async Task WebApiTemplateFSharp() => await WebApiTemplateCore(languageOverride: "F#"); - - [Fact] - public async Task WebApiTemplateCSharp() => await WebApiTemplateCore(languageOverride: null); - - private async Task WebApiTemplateCore(string languageOverride) - { - Project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output); - - var createResult = await Project.RunDotNetNewAsync("webapi", language: languageOverride); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var aspNetProcess = Project.StartBuiltProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - - await aspNetProcess.AssertOk("weatherforecast"); - await aspNetProcess.AssertNotFound("/"); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync()) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - - - await aspNetProcess.AssertOk("weatherforecast"); - await aspNetProcess.AssertNotFound("/"); - } - } - } -} diff --git a/src/ProjectTemplates/test/WorkerTemplateTest.cs b/src/ProjectTemplates/test/WorkerTemplateTest.cs deleted file mode 100644 index 738eafc61d6a..000000000000 --- a/src/ProjectTemplates/test/WorkerTemplateTest.cs +++ /dev/null @@ -1,56 +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.Threading.Tasks; -using Templates.Test.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Templates.Test -{ - public class WorkerTemplateTest - { - public WorkerTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) - { - ProjectFactory = projectFactory; - Output = output; - } - - public Project Project { get; set; } - public ProjectFactoryFixture ProjectFactory { get; } - public ITestOutputHelper Output { get; } - - [Fact] - public async Task WorkerTemplateAsync() - { - Project = await ProjectFactory.GetOrCreateProject("worker", Output); - - var createResult = await Project.RunDotNetNewAsync("worker"); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); - - var publishResult = await Project.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await Project.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); - - using (var aspNetProcess = Project.StartBuiltProjectAsync(hasListeningUri: false)) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); - } - - using (var aspNetProcess = Project.StartPublishedProjectAsync(hasListeningUri: false)) - { - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); - } - } - } -} From 7fc46862eafc386cedda04a0b20bd707e19cd3c8 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 3 Dec 2019 14:29:05 -0800 Subject: [PATCH 029/322] Run build and publish tests for Blazor templates (#17410) * Add build and publish tests for Blazor hosted * Add build tests for Blazor standalone * Cleanup project template Fixes https://github.com/aspnet/AspNetCore/issues/14866 Fixes https://github.com/aspnet/AspNetCore/issues/10269 Fixes https://github.com/aspnet/AspNetCore/issues/9168 --- eng/Build.props | 2 +- eng/common/tools.ps1 | 2 +- .../Templates/src/Directory.Build.props | 15 -- .../Templates/src/Directory.Build.targets | 17 -- ...crosoft.AspNetCore.Blazor.Templates.csproj | 64 -------- ...crosoft.AspNetCore.Blazor.Templates.nuspec | 16 -- src/Components/Components.sln | 17 +- .../BlazorWasm.ProjectTemplates/.gitignore | 3 + .../BlazorWasm-CSharp.Client.csproj.in} | 8 +- .../BlazorWasm-CSharp.Server.csproj.in} | 5 +- .../BlazorWasm-CSharp.Shared.csproj.in} | 1 - ...crosoft.AspNetCore.Blazor.Templates.csproj | 41 +++++ .../.template.config}/dotnetcli.host.json | 0 .../.template.config}/icon.png | Bin .../.template.config}/template.json | 20 +-- .../.template.config}/vs-2017.3.host.json | 2 +- .../BlazorWasm-CSharp/BlazorWasm-CSharp.sln | 0 .../BlazorWasm-CSharp/Client/App.razor | 0 .../Client/Pages/Counter.razor | 0 .../Client/Pages/FetchData.razor | 0 .../Client/Pages/Index.razor | 0 .../BlazorWasm-CSharp/Client/Program.cs | 0 .../Client/Shared/MainLayout.razor | 0 .../Client/Shared/NavMenu.razor | 0 .../Client/Shared/SurveyPrompt.razor | 0 .../BlazorWasm-CSharp/Client/Startup.cs | 0 .../BlazorWasm-CSharp/Client/_Imports.razor | 0 .../wwwroot/css/bootstrap/bootstrap.min.css | 0 .../css/bootstrap/bootstrap.min.css.map | 0 .../wwwroot/css/open-iconic/FONT-LICENSE | 0 .../wwwroot/css/open-iconic/ICON-LICENSE | 0 .../Client/wwwroot/css/open-iconic/README.md | 0 .../font/css/open-iconic-bootstrap.min.css | 0 .../open-iconic/font/fonts/open-iconic.eot | Bin .../open-iconic/font/fonts/open-iconic.otf | Bin .../open-iconic/font/fonts/open-iconic.svg | 0 .../open-iconic/font/fonts/open-iconic.ttf | Bin .../open-iconic/font/fonts/open-iconic.woff | Bin .../Client/wwwroot/css/site.css | 0 .../Client/wwwroot/index.html | 0 .../Client/wwwroot/sample-data/weather.json | 0 .../Controllers/WeatherForecastController.cs | 0 .../BlazorWasm-CSharp/Server/Program.cs | 0 .../BlazorWasm-CSharp/Server/Startup.cs | 0 .../Shared/WeatherForecast.cs | 0 .../content/Directory.Build.props | 0 .../content/Directory.Build.targets | 0 src/ProjectTemplates/ProjectTemplates.sln | 14 ++ .../test/BlazorWasmTemplateTest.cs | 155 ++++++++++++++++++ src/ProjectTemplates/test/Helpers/Project.cs | 10 +- .../test/Helpers/TemplatePackageInstaller.cs | 5 +- .../test/ProjectTemplates.Tests.csproj | 3 +- 52 files changed, 237 insertions(+), 163 deletions(-) delete mode 100644 src/Components/Blazor/Templates/src/Directory.Build.props delete mode 100644 src/Components/Blazor/Templates/src/Directory.Build.targets delete mode 100644 src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj delete mode 100644 src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj => ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in} (67%) rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj => ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in} (72%) rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj => ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in} (79%) create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src => ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config}/dotnetcli.host.json (100%) rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src => ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config}/icon.png (100%) rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src => ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config}/template.json (86%) rename src/{Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src => ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config}/vs-2017.3.host.json (92%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/App.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Pages/Counter.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Pages/Index.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Program.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/Startup.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/_Imports.razor (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/index.html (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Server/Program.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Server/Startup.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/Directory.Build.props (100%) rename src/{Components/Blazor/Templates/src => ProjectTemplates/BlazorWasm.ProjectTemplates}/content/Directory.Build.targets (100%) create mode 100644 src/ProjectTemplates/test/BlazorWasmTemplateTest.cs diff --git a/eng/Build.props b/eng/Build.props index 3378e22c3978..17c9848f831a 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -35,7 +35,7 @@ $(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj; $(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj; $(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj; - $(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj; + $(RepoRoot)src\ProjectTemplates\BlazorWasm.ProjectTemplates\content\**\*.csproj; $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj; $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj; $(RepoRoot)src\ProjectTemplates\Web.Spa.ProjectTemplates\content\**\*.csproj; diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 91efea9405e5..617db167ce66 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -228,7 +228,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = if ($msbuildCmd -ne $null) { # Workaround for https://github.com/dotnet/roslyn/issues/35793 # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+ - $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0]) + $msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split([char[]]@('-', '+'))[0]) if ($msbuildVersion -ge $vsMinVersion) { return $global:_MSBuildExe = $msbuildCmd.Path diff --git a/src/Components/Blazor/Templates/src/Directory.Build.props b/src/Components/Blazor/Templates/src/Directory.Build.props deleted file mode 100644 index ed5e01501483..000000000000 --- a/src/Components/Blazor/Templates/src/Directory.Build.props +++ /dev/null @@ -1,15 +0,0 @@ -<Project> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" /> - - <PropertyGroup> - <GenerateDocumentationFile>false</GenerateDocumentationFile> - <IncludeSymbols>false</IncludeSymbols> - </PropertyGroup> - - <PropertyGroup Label="Package Versions"> - <!-- Used only in development when running the template contents directly from source --> - <TemplateBlazorPackageVersion>0.8.0-preview-19064-0339</TemplateBlazorPackageVersion> - <TemplateComponentsPackageVersion>3.0.0-preview-19064-0339</TemplateComponentsPackageVersion> - </PropertyGroup> - -</Project> diff --git a/src/Components/Blazor/Templates/src/Directory.Build.targets b/src/Components/Blazor/Templates/src/Directory.Build.targets deleted file mode 100644 index 7c6f423adde2..000000000000 --- a/src/Components/Blazor/Templates/src/Directory.Build.targets +++ /dev/null @@ -1,17 +0,0 @@ -<Project> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" /> - - <Target Name="SetTemplateJsonSymbolReplacements"> - <PropertyGroup> - <!-- - Properties here will be injected into the template config *.json files - during the build, replacing tokens of the form ${PropertyName} - --> - <GeneratedContentProperties> - TemplateBlazorVersion=$(PackageVersion); - TemplateComponentsVersion=$(ComponentsPackageVersion); - RepositoryCommit=$(SourceRevisionId); - </GeneratedContentProperties> - </PropertyGroup> - </Target> -</Project> diff --git a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj deleted file mode 100644 index c91a32128d65..000000000000 --- a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj +++ /dev/null @@ -1,64 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFramework>netstandard2.0</TargetFramework> - <NuspecFile>Microsoft.AspNetCore.Blazor.Templates.nuspec</NuspecFile> - <IsShippingPackage>true</IsShippingPackage> - <EnableDefaultItems>False</EnableDefaultItems> - <GenerateAssemblyInfo>False</GenerateAssemblyInfo> - <IncludeBuildOutput>False</IncludeBuildOutput> - <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory> - <DebugType>none</DebugType> - <GenerateDocumentationFile>false</GenerateDocumentationFile> - <NoWarn>$(NoWarn);2008</NoWarn> - <Description>Templates for ASP.NET Core Blazor projects.</Description> - <PackageTags>aspnet;templates;blazor;spa</PackageTags> - <IsProjectReferenceProvider>false</IsProjectReferenceProvider> - </PropertyGroup> - - <ItemGroup> - <UpToDateCheckInput Include="content\**\.template.config.src\**\*.*" /> - </ItemGroup> - - <Target Name="PrepareFileLists" AfterTargets="PrepareForBuild"> - <ItemGroup> - <_TemplateConfigMainFile Include="content\**\.template.config.src\template.json" /> - <_TemplateConfigDir Include="@(_TemplateConfigMainFile->'$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigMainFile.FullPath)'))')" /> - <_TemplateConfigFileToCopy Include="%(_TemplateConfigDir.Identity)\**\*.*"> - <DestDir>$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigDir.Identity)'))\.template.config\</DestDir> - </_TemplateConfigFileToCopy> - </ItemGroup> - </Target> - - <Target - Name="TransformTemplateConfigs" - BeforeTargets="CoreBuild" - DependsOnTargets="SetTemplateJsonSymbolReplacements" - Inputs="@(_TemplateConfigFileToCopy)" - Outputs="@(_TemplateConfigFileToCopy->'%(DestDir)%(FileName)%(Extension)')"> - - <!-- - For each template, copy its '.template.config.src' directory to '.template.config', - removing any earlier output at that location - --> - <RemoveDir Directories="%(_TemplateConfigFileToCopy.DestDir)" /> - <Copy SourceFiles="%(_TemplateConfigFileToCopy.Identity)" DestinationFolder="%(_TemplateConfigFileToCopy.DestDir)" /> - - <!-- - Modify the .json files in the .template.config dirs to stamp MSBuild properties into them - --> - <ItemGroup> - <GeneratedContent Include="@(_TemplateConfigFileToCopy->WithMetadataValue('Extension','.json'))"> - <OutputPath>%(DestDir)%(RecursiveDir)%(Filename)%(Extension)</OutputPath> - <Properties>$(GeneratedContentProperties)</Properties> - </GeneratedContent> - </ItemGroup> - <GenerateFileFromTemplate - TemplateFile="%(GeneratedContent.Identity)" - Properties="%(GeneratedContent.Properties)" - OutputPath="%(GeneratedContent.OutputPath)"> - - <Output TaskParameter="OutputPath" ItemName="FileWrites" /> - <Output TaskParameter="OutputPath" ItemName="Content" /> - </GenerateFileFromTemplate> - </Target> -</Project> diff --git a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec b/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec deleted file mode 100644 index fd1975023109..000000000000 --- a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> - <metadata> - $CommonMetadataElements$ - <packageTypes> - <packageType name="Template" /> - </packageTypes> - </metadata> - <files> - $CommonFileElements$ - <file - src="content/**" - exclude="**/bin/**;**/obj/**;**/.template.config.src/**;content/Directory.Build.props;content/Directory.Build.targets;" - target="Content" /> - </files> -</package> diff --git a/src/Components/Components.sln b/src/Components/Components.sln index 36cde86285d3..b4d18400258b 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -25,8 +25,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Templates", "Blazor\Templates\src\Microsoft.AspNetCore.Blazor.Templates.csproj", "{66036B70-6C93-4E45-A1A1-819F15CA757A}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{A7ABAC29-F73F-456D-AE54-46842CFC2E10}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{FD37F740-A654-4117-BFB6-9112CE4C1D3B}" @@ -248,7 +246,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -368,18 +366,6 @@ Global {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x64.Build.0 = Release|Any CPU {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.ActiveCfg = Release|Any CPU {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.Build.0 = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x64.ActiveCfg = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x64.Build.0 = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x86.ActiveCfg = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x86.Build.0 = Debug|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|Any CPU.Build.0 = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x64.ActiveCfg = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x64.Build.0 = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x86.ActiveCfg = Release|Any CPU - {66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x86.Build.0 = Release|Any CPU {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -1546,7 +1532,6 @@ Global {A6C8050D-7C18-4585-ADCF-833AC1765847} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {66036B70-6C93-4E45-A1A1-819F15CA757A} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {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} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore new file mode 100644 index 000000000000..9310b1ea5295 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore @@ -0,0 +1,3 @@ +# This file is generated by the build +content/*/*.*proj +content/*/*/*.*proj diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in similarity index 67% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in index c855c49821f3..70927b08e331 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in @@ -6,10 +6,10 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Blazor" Version="$(TemplateBlazorPackageVersion)" /> - <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="$(TemplateBlazorPackageVersion)" PrivateAssets="all" /> - <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="$(TemplateBlazorPackageVersion)" /> - <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="$(TemplateBlazorPackageVersion)" PrivateAssets="all" /> + <PackageReference Include="Microsoft.AspNetCore.Blazor" Version="${MicrosoftAspNetCoreBlazorPackageVersion}" /> + <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="${MicrosoftAspNetCoreBlazorBuildPackageVersion}" PrivateAssets="all" /> + <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="${MicrosoftAspNetCoreBlazorDevServerPackageVersion}" PrivateAssets="all" /> + <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="${MicrosoftAspNetCoreBlazorHttpClientPackageVersion}" /> </ItemGroup> <!--#if Hosted --> <ItemGroup> diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in similarity index 72% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in index 2742595431f2..5fe7473679dc 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in @@ -1,12 +1,11 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> - <LangVersion>7.3</LangVersion> + <TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework> </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="$(TemplateBlazorPackageVersion)" /> + <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="${MicrosoftAspNetCoreBlazorServerPackageVersion}" /> </ItemGroup> <ItemGroup> diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in similarity index 79% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in index d849ca903629..d4c395e8cb78 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in @@ -2,7 +2,6 @@ <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> - <LangVersion>7.3</LangVersion> </PropertyGroup> </Project> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj new file mode 100644 index 000000000000..32c3197d04f7 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj @@ -0,0 +1,41 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> + <IsShippingPackage>true</IsShippingPackage> + <Description>Templates for ASP.NET Core Blazor projects.</Description> + <PackageTags>$(PackageTags);blazor;spa</PackageTags> + </PropertyGroup> + + <PropertyGroup> + <!-- Lists the versions of dependencies not built in this repo. Packages produced from this repo should be listed as a PackageVersionVariableReference. --> + <GeneratedContentProperties> + DefaultNetCoreTargetFramework=$(DefaultNetCoreTargetFramework); + MicrosoftAspNetCoreBlazorPackageVersion=$(MicrosoftAspNetCoreBlazorPackageVersion); + MicrosoftAspNetCoreBlazorBuildPackageVersion=$(MicrosoftAspNetCoreBlazorBuildPackageVersion); + MicrosoftAspNetCoreBlazorDevServerPackageVersion=$(MicrosoftAspNetCoreBlazorDevServerPackageVersion); + MicrosoftAspNetCoreBlazorHttpClientPackageVersion=$(MicrosoftAspNetCoreBlazorHttpClientPackageVersion); + MonoWebAssemblyInteropPackageVersion=$(MonoWebAssemblyInteropPackageVersion); + MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); + MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion); + </GeneratedContentProperties> + + <BlazorProjectsRoot>$(RepoRoot)src\Components\Blazor\</BlazorProjectsRoot> + </PropertyGroup> + + <ItemGroup> + <!-- These projects product packages that the templates depend on. See GenerateContent.targets --> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Blazor\src\Microsoft.AspNetCore.Blazor.csproj" /> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Build\src\Microsoft.AspNetCore.Blazor.Build.csproj" /> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj" /> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" /> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" /> + <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Server\src\Microsoft.AspNetCore.Blazor.Server.csproj" /> + </ItemGroup> + + <ItemGroup> + <GeneratedContent Include="BlazorWasm-CSharp.Client.csproj.in" OutputPath="content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj" /> + <GeneratedContent Include="BlazorWasm-CSharp.Shared.csproj.in" OutputPath="content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj" /> + <GeneratedContent Include="BlazorWasm-CSharp.Server.csproj.in" OutputPath="content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj" /> + </ItemGroup> + +</Project> diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/dotnetcli.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/dotnetcli.host.json rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/icon.png b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/icon.png similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/icon.png rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/icon.png diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json similarity index 86% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json index 33e094e35668..b6cb64fcec5f 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json @@ -1,13 +1,16 @@ { + "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "Web", "Blazor", "WebAssembly" ], + "name": "Blazor WebAssembly App", "defaultName": "WebApplication", "description": "A project template for creating a Blazor app that runs on WebAssembly and is optionally hosted by an ASP.NET Core app. This template can be used for web apps with rich dynamic user interfaces (UIs).", "groupIdentity": "Microsoft.Web.Blazor.Wasm", + "precedence": "6001", "guids": [ "4C26868E-5E7C-458D-82E3-040509D0C71F", "5990939C-7E7B-4CFA-86FF-44CA5756498A", @@ -15,7 +18,6 @@ "0AFFA7FD-4E37-4636-AB91-3753E746DB98" ], "identity": "Microsoft.Web.Blazor.Wasm.CSharp", - "name": "Blazor WebAssembly App", "preferNameDirectory": true, "primaryOutputs": [ { @@ -94,20 +96,6 @@ "type": "bind", "binding": "HostIdentifier" }, - "TemplateBlazorVersionSymbol": { - "type": "parameter", - "datatype": "string", - "description": "Specifies which version of Blazor packages to use.", - "replaces": "$(TemplateBlazorPackageVersion)", - "defaultValue": "${TemplateBlazorVersion}" - }, - "TemplateComponentsVersionSymbol": { - "type": "parameter", - "datatype": "string", - "description": "Specifies which version of Components packages to use.", - "replaces": "$(TemplateComponentsPackageVersion)", - "defaultValue": "${TemplateComponentsVersion}" - }, "skipRestore": { "type": "parameter", "datatype": "bool", @@ -146,7 +134,7 @@ } ], "args": { - "files": [ "BlazorWasm-CSharp.Client.csproj" ] + "files": ["BlazorWasm-CSharp.Client.csproj"] }, "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", "continueOnError": true diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/vs-2017.3.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json similarity index 92% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/vs-2017.3.host.json rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json index 4d0b04c1b3a3..5cb50d10a519 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/vs-2017.3.host.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json @@ -11,7 +11,7 @@ }, "order": 610, "icon": "icon.png", - "learnMoreLink": "https://github.com/aspnet/blazor", + "learnMoreLink": "https://github.com/aspnet/AspNetCore", "uiFilters": [ "oneaspnet" ], diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Counter.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Counter.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Counter.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Counter.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Index.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Index.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Index.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Index.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/_Imports.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/_Imports.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/index.html b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/index.html similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/index.html rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/index.html diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Program.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Program.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Program.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Program.cs diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Startup.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs similarity index 100% rename from src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs diff --git a/src/Components/Blazor/Templates/src/content/Directory.Build.props b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.props similarity index 100% rename from src/Components/Blazor/Templates/src/content/Directory.Build.props rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.props diff --git a/src/Components/Blazor/Templates/src/content/Directory.Build.targets b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.targets similarity index 100% rename from src/Components/Blazor/Templates/src/content/Directory.Build.targets rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.targets diff --git a/src/ProjectTemplates/ProjectTemplates.sln b/src/ProjectTemplates/ProjectTemplates.sln index da18f3a2e57d..7628d8233da8 100644 --- a/src/ProjectTemplates/ProjectTemplates.sln +++ b/src/ProjectTemplates/ProjectTemplates.sln @@ -177,6 +177,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ApiAut EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SpaServices.Extensions", "..\Middleware\SpaServices.Extensions\src\Microsoft.AspNetCore.SpaServices.Extensions.csproj", "{06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Templates", "BlazorWasm.ProjectTemplates\Microsoft.AspNetCore.Blazor.Templates.csproj", "{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1231,6 +1233,18 @@ Global {06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x64.Build.0 = Release|Any CPU {06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x86.ActiveCfg = Release|Any CPU {06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x86.Build.0 = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x64.ActiveCfg = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x64.Build.0 = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x86.ActiveCfg = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x86.Build.0 = Debug|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|Any CPU.Build.0 = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x64.ActiveCfg = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x64.Build.0 = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x86.ActiveCfg = Release|Any CPU + {C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs new file mode 100644 index 000000000000..579d5b11bf13 --- /dev/null +++ b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs @@ -0,0 +1,155 @@ +// 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.Net; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; +using OpenQA.Selenium; +using Templates.Test.Helpers; +using Xunit; +using Xunit.Abstractions; + +namespace Templates.Test +{ + public class BlazorWasmTemplateTest : BrowserTestBase + { + public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) + : base(browserFixture, output) + { + ProjectFactory = projectFactory; + } + + public ProjectFactoryFixture ProjectFactory { get; set; } + + [Fact] + public async Task BlazorWasmStandaloneTemplate_Works() + { + var project = await ProjectFactory.GetOrCreateProject("blazorstandalone", Output); + + var createResult = await project.RunDotNetNewAsync("blazorwasm"); + Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); + + // We can't run a published standalone app, but let's just make sure it publishes fine + var publishResult = await project.RunDotNetPublishAsync(); + Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult)); + + var buildResult = await project.RunDotNetBuildAsync(); + Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult)); + + await BuildAndRunTest(project.ProjectName, project); + } + + [Fact] + public async Task BlazorWasmHostedTemplate_Works() + { + var project = await ProjectFactory.GetOrCreateProject("blazorhosted", Output); + + var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "--hosted" }); + Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); + + var serverProject = GetSubProject(project, "Server", $"{project.ProjectName}.Server"); + + var publishResult = await serverProject.RunDotNetPublishAsync(); + Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", serverProject, publishResult)); + + var buildResult = await serverProject.RunDotNetBuildAsync(); + Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", serverProject, buildResult)); + + await BuildAndRunTest(project.ProjectName, serverProject); + + using var aspNetProcess = serverProject.StartPublishedProjectAsync(); + + Assert.False( + aspNetProcess.Process.HasExited, + ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", serverProject, aspNetProcess.Process)); + + await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); + if (BrowserFixture.IsHostAutomationSupported()) + { + aspNetProcess.VisitInBrowser(Browser); + TestBasicNavigation(project.ProjectName, serverProject); + } + else + { + BrowserFixture.EnforceSupportedConfigurations(); + } + } + + protected async Task BuildAndRunTest(string appName, Project project) + { + using var aspNetProcess = project.StartBuiltProjectAsync(); + + Assert.False( + aspNetProcess.Process.HasExited, + ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process)); + + await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); + if (BrowserFixture.IsHostAutomationSupported()) + { + aspNetProcess.VisitInBrowser(Browser); + TestBasicNavigation(appName, project); + } + else + { + BrowserFixture.EnforceSupportedConfigurations(); + } + } + + private void TestBasicNavigation(string appName, Project project) + { + // Give components.server enough time to load so that it can replace + // the prerendered content before we start making assertions. + Thread.Sleep(5000); + Browser.Exists(By.TagName("ul")); + + // <title> element gets project ID injected into it during template execution + Browser.Equal(appName.Trim(), () => Browser.Title.Trim()); + + // Initially displays the home page + Browser.Equal("Hello, world!", () => Browser.FindElement(By.TagName("h1")).Text); + + // Can navigate to the counter page + Browser.FindElement(By.PartialLinkText("Counter")).Click(); + Browser.Contains("counter", () => Browser.Url); + Browser.Equal("Counter", () => Browser.FindElement(By.TagName("h1")).Text); + + // Clicking the counter button works + Browser.Equal("Current count: 0", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); + Browser.FindElement(By.CssSelector("p+button")).Click(); + Browser.Equal("Current count: 1", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); + + // Can navigate to the 'fetch data' page + Browser.FindElement(By.PartialLinkText("Fetch data")).Click(); + Browser.Contains("fetchdata", () => Browser.Url); + Browser.Equal("Weather forecast", () => Browser.FindElement(By.TagName("h1")).Text); + + // Asynchronously loads and displays the table of weather forecasts + Browser.Exists(By.CssSelector("table>tbody>tr")); + Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count); + } + + private Project GetSubProject(Project project, string projectDirectory, string projectName) + { + var subProjectDirectory = Path.Combine(project.TemplateOutputDir, projectDirectory); + if (!Directory.Exists(subProjectDirectory)) + { + throw new DirectoryNotFoundException($"Directory {subProjectDirectory} was not found."); + } + + var subProject = new Project + { + DotNetNewLock = project.DotNetNewLock, + NodeLock = project.NodeLock, + Output = project.Output, + DiagnosticsMessageSink = project.DiagnosticsMessageSink, + ProjectName = projectName, + TemplateOutputDir = subProjectDirectory, + }; + + return subProject; + } + } +} diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs index fc6923ae5c59..8eb59d86f62b 100644 --- a/src/ProjectTemplates/test/Helpers/Project.cs +++ b/src/ProjectTemplates/test/Helpers/Project.cs @@ -110,7 +110,7 @@ internal async Task<ProcessEx> RunDotNetNewAsync( } } - internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null) + internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null) { Output.WriteLine("Publishing ASP.NET application..."); @@ -121,7 +121,7 @@ internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, await effectiveLock.WaitAsync(); try { - var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release /bl", packageOptions); + var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release /bl /nr:false {additionalArgs}", packageOptions); await result.Exited; CaptureBinLogOnFailure(result); return result; @@ -132,7 +132,7 @@ internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, } } - internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null) + internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null) { Output.WriteLine("Building ASP.NET application..."); @@ -143,7 +143,7 @@ internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, ID await effectiveLock.WaitAsync(); try { - var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), "build -c Debug /bl", packageOptions); + var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"build -c Debug /bl /nr:false {additionalArgs}", packageOptions); await result.Exited; CaptureBinLogOnFailure(result); return result; @@ -211,7 +211,7 @@ internal AspNetProcess StartBuiltProjectAsync(bool hasListeningUri = true) }; var projectDll = Path.Combine(TemplateBuildDir, $"{ProjectName}.dll"); - return new AspNetProcess(Output, TemplateOutputDir, projectDll, environment, hasListeningUri: hasListeningUri); + return new AspNetProcess(Output, TemplateOutputDir, projectDll, environment, published: false, hasListeningUri: hasListeningUri); } internal AspNetProcess StartPublishedProjectAsync(bool hasListeningUri = true) diff --git a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs index 2c3425959208..5d6985f691d8 100644 --- a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs @@ -36,7 +36,8 @@ internal static class TemplatePackageInstaller "Microsoft.DotNet.Web.Spa.ProjectTemplates.2.2", "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0", "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1", - "Microsoft.DotNet.Web.Spa.ProjectTemplates" + "Microsoft.DotNet.Web.Spa.ProjectTemplates", + "Microsoft.AspNetCore.Blazor.Templates", }; public static string CustomHivePath { get; } = typeof(TemplatePackageInstaller) @@ -86,7 +87,7 @@ private static async Task InstallTemplatePackages(ITestOutputHelper output) .Where(p => _templatePackages.Any(t => Path.GetFileName(p).StartsWith(t, StringComparison.OrdinalIgnoreCase))) .ToArray(); - Assert.Equal(4, builtPackages.Length); + Assert.Equal(5, builtPackages.Length); /* * The templates are indexed by path, for example: diff --git a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj index b8797c13451e..492f337109f4 100644 --- a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj +++ b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj @@ -46,6 +46,7 @@ <ProjectReference Include="../Web.ItemTemplates/Microsoft.DotNet.Web.ItemTemplates.csproj" ReferenceOutputAssembly="false" /> <ProjectReference Include="../Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj" ReferenceOutputAssembly="false" /> <ProjectReference Include="../Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj" ReferenceOutputAssembly="false" /> + <ProjectReference Include="../BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj" ReferenceOutputAssembly="false" /> </ItemGroup> <ItemGroup> @@ -79,7 +80,7 @@ <_Parameter1>ArtifactsLogDir</_Parameter1> <_Parameter2>$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'log'))</_Parameter2> </AssemblyAttribute> - + <AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute"> <_Parameter1>ArtifactsNonShippingPackagesDir</_Parameter1> <_Parameter2>$(ArtifactsNonShippingPackagesDir)</_Parameter2> From 0a73b55d4164bda06a5c8f8e8f90fac8d9d52774 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Wed, 4 Dec 2019 14:52:31 -0800 Subject: [PATCH 030/322] Rollback to 3.1.0 RTM versions --- eng/Versions.props | 92 +++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index ded3d6ce382a..67fb31b526e8 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -103,61 +103,61 @@ <MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion> <MicrosoftAspNetCoreTestingPackageVersion>3.1.0-rtm.19575.5</MicrosoftAspNetCoreTestingPackageVersion> <MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion> - <MicrosoftExtensionsCachingAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsCachingAbstractionsPackageVersion> - <MicrosoftExtensionsCachingMemoryPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsCachingMemoryPackageVersion> - <MicrosoftExtensionsCachingSqlServerPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsCachingSqlServerPackageVersion> - <MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion> + <MicrosoftExtensionsCachingAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsCachingAbstractionsPackageVersion> + <MicrosoftExtensionsCachingMemoryPackageVersion>3.1.0</MicrosoftExtensionsCachingMemoryPackageVersion> + <MicrosoftExtensionsCachingSqlServerPackageVersion>3.1.0</MicrosoftExtensionsCachingSqlServerPackageVersion> + <MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.1.0</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion> <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion> - <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationAbstractionsPackageVersion> - <MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion> - <MicrosoftExtensionsConfigurationBinderPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationBinderPackageVersion> - <MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationCommandLinePackageVersion> - <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion> - <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion> - <MicrosoftExtensionsConfigurationIniPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationIniPackageVersion> - <MicrosoftExtensionsConfigurationJsonPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationJsonPackageVersion> - <MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion> - <MicrosoftExtensionsConfigurationPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationPackageVersion> - <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationUserSecretsPackageVersion> - <MicrosoftExtensionsConfigurationXmlPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsConfigurationXmlPackageVersion> - <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion> - <MicrosoftExtensionsDependencyInjectionPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsDependencyInjectionPackageVersion> - <MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsDiagnosticAdapterPackageVersion> - <MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion> - <MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion> - <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion> - <MicrosoftExtensionsFileProvidersCompositePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsFileProvidersCompositePackageVersion> - <MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion> - <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsFileProvidersPhysicalPackageVersion> - <MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsFileSystemGlobbingPackageVersion> + <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsConfigurationAbstractionsPackageVersion> + <MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.1.0</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion> + <MicrosoftExtensionsConfigurationBinderPackageVersion>3.1.0</MicrosoftExtensionsConfigurationBinderPackageVersion> + <MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.1.0</MicrosoftExtensionsConfigurationCommandLinePackageVersion> + <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.1.0</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion> + <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.1.0</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion> + <MicrosoftExtensionsConfigurationIniPackageVersion>3.1.0</MicrosoftExtensionsConfigurationIniPackageVersion> + <MicrosoftExtensionsConfigurationJsonPackageVersion>3.1.0</MicrosoftExtensionsConfigurationJsonPackageVersion> + <MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.1.0</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion> + <MicrosoftExtensionsConfigurationPackageVersion>3.1.0</MicrosoftExtensionsConfigurationPackageVersion> + <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.1.0</MicrosoftExtensionsConfigurationUserSecretsPackageVersion> + <MicrosoftExtensionsConfigurationXmlPackageVersion>3.1.0</MicrosoftExtensionsConfigurationXmlPackageVersion> + <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion> + <MicrosoftExtensionsDependencyInjectionPackageVersion>3.1.0</MicrosoftExtensionsDependencyInjectionPackageVersion> + <MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.1.0</MicrosoftExtensionsDiagnosticAdapterPackageVersion> + <MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion> + <MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.1.0</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion> + <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion> + <MicrosoftExtensionsFileProvidersCompositePackageVersion>3.1.0</MicrosoftExtensionsFileProvidersCompositePackageVersion> + <MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.1.0</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion> + <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.1.0</MicrosoftExtensionsFileProvidersPhysicalPackageVersion> + <MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.1.0</MicrosoftExtensionsFileSystemGlobbingPackageVersion> <MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion> - <MicrosoftExtensionsHostingAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsHostingAbstractionsPackageVersion> - <MicrosoftExtensionsHostingPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsHostingPackageVersion> + <MicrosoftExtensionsHostingAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsHostingAbstractionsPackageVersion> + <MicrosoftExtensionsHostingPackageVersion>3.1.0</MicrosoftExtensionsHostingPackageVersion> <MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion> - <MicrosoftExtensionsHttpPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsHttpPackageVersion> - <MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLocalizationAbstractionsPackageVersion> - <MicrosoftExtensionsLocalizationPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLocalizationPackageVersion> - <MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingAbstractionsPackageVersion> - <MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion> - <MicrosoftExtensionsLoggingConfigurationPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingConfigurationPackageVersion> - <MicrosoftExtensionsLoggingConsolePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingConsolePackageVersion> - <MicrosoftExtensionsLoggingDebugPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingDebugPackageVersion> - <MicrosoftExtensionsLoggingEventSourcePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingEventSourcePackageVersion> - <MicrosoftExtensionsLoggingEventLogPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingEventLogPackageVersion> - <MicrosoftExtensionsLoggingPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingPackageVersion> + <MicrosoftExtensionsHttpPackageVersion>3.1.0</MicrosoftExtensionsHttpPackageVersion> + <MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsLocalizationAbstractionsPackageVersion> + <MicrosoftExtensionsLocalizationPackageVersion>3.1.0</MicrosoftExtensionsLocalizationPackageVersion> + <MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.1.0</MicrosoftExtensionsLoggingAbstractionsPackageVersion> + <MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.1.0</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion> + <MicrosoftExtensionsLoggingConfigurationPackageVersion>3.1.0</MicrosoftExtensionsLoggingConfigurationPackageVersion> + <MicrosoftExtensionsLoggingConsolePackageVersion>3.1.0</MicrosoftExtensionsLoggingConsolePackageVersion> + <MicrosoftExtensionsLoggingDebugPackageVersion>3.1.0</MicrosoftExtensionsLoggingDebugPackageVersion> + <MicrosoftExtensionsLoggingEventSourcePackageVersion>3.1.0</MicrosoftExtensionsLoggingEventSourcePackageVersion> + <MicrosoftExtensionsLoggingEventLogPackageVersion>3.1.0</MicrosoftExtensionsLoggingEventLogPackageVersion> + <MicrosoftExtensionsLoggingPackageVersion>3.1.0</MicrosoftExtensionsLoggingPackageVersion> <MicrosoftExtensionsLoggingTestingPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingTestingPackageVersion> - <MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsLoggingTraceSourcePackageVersion> - <MicrosoftExtensionsObjectPoolPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsObjectPoolPackageVersion> - <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion> - <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion> - <MicrosoftExtensionsOptionsPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsOptionsPackageVersion> + <MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.1.0</MicrosoftExtensionsLoggingTraceSourcePackageVersion> + <MicrosoftExtensionsObjectPoolPackageVersion>3.1.0</MicrosoftExtensionsObjectPoolPackageVersion> + <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.1.0</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion> + <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.1.0</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion> + <MicrosoftExtensionsOptionsPackageVersion>3.1.0</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion> <MicrosoftExtensionsPrimitivesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsPrimitivesPackageVersion> <MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion> <MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsValueStopwatchSourcesPackageVersion> - <MicrosoftExtensionsWebEncodersPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsWebEncodersPackageVersion> + <MicrosoftExtensionsWebEncodersPackageVersion>3.1.0</MicrosoftExtensionsWebEncodersPackageVersion> <MicrosoftInternalExtensionsRefsPackageVersion>3.1.0-rtm.19565.4</MicrosoftInternalExtensionsRefsPackageVersion> - <MicrosoftJSInteropPackageVersion>3.1.0-rtm.19575.5</MicrosoftJSInteropPackageVersion> + <MicrosoftJSInteropPackageVersion>3.1.0</MicrosoftJSInteropPackageVersion> <MonoWebAssemblyInteropPackageVersion>3.1.0-preview4.19575.5</MonoWebAssemblyInteropPackageVersion> <!-- Packages from aspnet/EntityFrameworkCore --> <dotnetefPackageVersion>3.1.0</dotnetefPackageVersion> From ce5065509b8412421ccc4d0b141dbe0526d8d371 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Wed, 4 Dec 2019 15:06:50 -0800 Subject: [PATCH 031/322] Fixup missed version --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 67fb31b526e8..06986905cc8b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -152,7 +152,7 @@ <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.1.0</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>3.1.0</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion> - <MicrosoftExtensionsPrimitivesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsPrimitivesPackageVersion> + <MicrosoftExtensionsPrimitivesPackageVersion>3.1.0</MicrosoftExtensionsPrimitivesPackageVersion> <MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion> <MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.1.0-rtm.19575.5</MicrosoftExtensionsValueStopwatchSourcesPackageVersion> <MicrosoftExtensionsWebEncodersPackageVersion>3.1.0</MicrosoftExtensionsWebEncodersPackageVersion> From 3fba107522a817ab681fbeefb8b67087f7020407 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 10 Dec 2019 11:30:13 -0800 Subject: [PATCH 032/322] Fix typo in error message (#17741) --- src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs index 527f302a463c..5e0a86d384e4 100644 --- a/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs +++ b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs @@ -168,7 +168,7 @@ protected override string GenerateResponseFileCommands() protected override bool HandleTaskExecutionErrors() { // Show a slightly better error than the standard ToolTask message that says "dotnet" failed. - Log.LogError($"ILLink failed with exited code {ExitCode}."); + Log.LogError($"ILLink failed with exit code {ExitCode}."); return false; } From 3a93704737cceb38c4d51ae03075cf4eaad81b23 Mon Sep 17 00:00:00 2001 From: Steve Sanderson <SteveSandersonMS@users.noreply.github.com> Date: Thu, 12 Dec 2019 15:05:12 +0000 Subject: [PATCH 033/322] Support async main (#17673) --- .../Blazor/src/Hosting/EntrypointInvoker.cs | 89 ++++++++++ .../test/Hosting/EntrypointInvokerTest.cs | 153 ++++++++++++++++++ .../Microsoft.AspNetCore.Blazor.Tests.csproj | 3 +- .../StandaloneApp/wwwroot/index.html | 8 +- src/Components/Components.sln | 15 ++ src/Components/Web.JS/src/Boot.WebAssembly.ts | 4 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 22 ++- .../Web.JS/src/Platform/Platform.ts | 2 +- .../ServerErrorNotificationTest.cs} | 5 +- ...ntSideTest.cs => ErrorNotificationTest.cs} | 4 +- .../Tests/StartupErrorNotificationTest.cs | 40 +++++ .../test/testassets/BasicTestApp/Index.razor | 6 - .../test/testassets/BasicTestApp/Program.cs | 24 ++- .../BasicTestApp/wwwroot/index.html | 11 ++ .../testassets/BasicTestApp/wwwroot/style.css | 14 +- .../TestServer/Pages/_ServerHost.cshtml | 6 + 16 files changed, 381 insertions(+), 25 deletions(-) create mode 100644 src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs create mode 100644 src/Components/Blazor/Blazor/test/Hosting/EntrypointInvokerTest.cs rename src/Components/test/E2ETest/{Tests/ErrorNotificationServerSideTest.cs => ServerExecutionTests/ServerErrorNotificationTest.cs} (85%) rename src/Components/test/E2ETest/Tests/{ErrorNotificationClientSideTest.cs => ErrorNotificationTest.cs} (94%) create mode 100644 src/Components/test/E2ETest/Tests/StartupErrorNotificationTest.cs diff --git a/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs b/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs new file mode 100644 index 000000000000..bce063bcf56f --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs @@ -0,0 +1,89 @@ +// 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; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Blazor.Hosting +{ + internal static class EntrypointInvoker + { + // This method returns void because currently the JS side is not listening to any result, + // nor will it handle any exceptions. We handle all exceptions internally to this method. + // In the future we may want Blazor.start to return something that exposes the possibly-async + // entrypoint result to the JS caller. There's no requirement to do that today, and if we + // do change this it will be non-breaking. + public static void InvokeEntrypoint(string assemblyName, string[] args) + { + object entrypointResult; + try + { + var assembly = Assembly.Load(assemblyName); + var entrypoint = FindUnderlyingEntrypoint(assembly); + var @params = entrypoint.GetParameters().Length == 1 ? new object[] { args } : new object[] { }; + entrypointResult = entrypoint.Invoke(null, @params); + } + catch (Exception syncException) + { + HandleStartupException(syncException); + return; + } + + // If the entrypoint is async, handle async exceptions in the same way that we would + // have handled sync ones + if (entrypointResult is Task entrypointTask) + { + entrypointTask.ContinueWith(task => + { + if (task.Exception != null) + { + HandleStartupException(task.Exception); + } + }); + } + } + + private static MethodBase FindUnderlyingEntrypoint(Assembly assembly) + { + // This is the entrypoint declared in .NET metadata. In the case of async main, it's the + // compiler-generated wrapper method. Otherwise it's the developer-defined method. + var metadataEntrypointMethodBase = assembly.EntryPoint; + + // For "async Task Main", the C# compiler generates a method called "<Main>" + // that is marked as the assembly entrypoint. Detect this case, and instead of + // calling "<Whatever>", call the sibling "Whatever". + if (metadataEntrypointMethodBase.IsSpecialName) + { + var origName = metadataEntrypointMethodBase.Name; + var origNameLength = origName.Length; + if (origNameLength > 2) + { + var candidateMethodName = origName.Substring(1, origNameLength - 2); + var candidateMethod = metadataEntrypointMethodBase.DeclaringType.GetMethod( + candidateMethodName, + BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, + null, + metadataEntrypointMethodBase.GetParameters().Select(p => p.ParameterType).ToArray(), + null); + + if (candidateMethod != null) + { + return candidateMethod; + } + } + } + + // Either it's not async main, or for some reason we couldn't locate the underlying entrypoint, + // so use the one from assembly metadata. + return metadataEntrypointMethodBase; + } + + private static void HandleStartupException(Exception exception) + { + // Logs to console, and causes the error UI to appear + Console.Error.WriteLine(exception); + } + } +} diff --git a/src/Components/Blazor/Blazor/test/Hosting/EntrypointInvokerTest.cs b/src/Components/Blazor/Blazor/test/Hosting/EntrypointInvokerTest.cs new file mode 100644 index 000000000000..60a3d1638b8f --- /dev/null +++ b/src/Components/Blazor/Blazor/test/Hosting/EntrypointInvokerTest.cs @@ -0,0 +1,153 @@ +// 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.Reflection; +using System.Runtime.Loader; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Hosting +{ + public class EntrypointInvokerTest + { + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void InvokesEntrypoint_Sync_Success(bool hasReturnValue, bool hasParams) + { + // Arrange + var returnType = hasReturnValue ? "int" : "void"; + var paramsDecl = hasParams ? "string[] args" : string.Empty; + var returnStatement = hasReturnValue ? "return 123;" : "return;"; + var assembly = CompileToAssembly(@" +static " + returnType + @" Main(" + paramsDecl + @") +{ + DidMainExecute = true; + " + returnStatement + @" +}", out var didMainExecute); + + // Act + EntrypointInvoker.InvokeEntrypoint(assembly.FullName, new string[] { }); + + // Assert + Assert.True(didMainExecute()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void InvokesEntrypoint_Async_Success(bool hasReturnValue, bool hasParams) + { + // Arrange + var returnTypeGenericParam = hasReturnValue ? "<int>" : string.Empty; + var paramsDecl = hasParams ? "string[] args" : string.Empty; + var returnStatement = hasReturnValue ? "return 123;" : "return;"; + var assembly = CompileToAssembly(@" +public static TaskCompletionSource<object> ContinueTcs { get; } = new TaskCompletionSource<object>(); + +static async Task" + returnTypeGenericParam + @" Main(" + paramsDecl + @") +{ + await ContinueTcs.Task; + DidMainExecute = true; + " + returnStatement + @" +}", out var didMainExecute); + + // Act/Assert 1: Waits for task + // The fact that we're not blocking here proves that we're not executing the + // metadata-declared entrypoint, as that would block + EntrypointInvoker.InvokeEntrypoint(assembly.FullName, new string[] { }); + Assert.False(didMainExecute()); + + // Act/Assert 2: Continues + var tcs = (TaskCompletionSource<object>)assembly.GetType("SomeApp.Program").GetProperty("ContinueTcs").GetValue(null); + tcs.SetResult(null); + Assert.True(didMainExecute()); + } + + [Fact] + public void InvokesEntrypoint_Sync_Exception() + { + // Arrange + var assembly = CompileToAssembly(@" +public static void Main() +{ + DidMainExecute = true; + throw new InvalidTimeZoneException(""Test message""); +}", out var didMainExecute); + + // Act/Assert + // The fact that this doesn't throw shows that EntrypointInvoker is doing something + // to handle the exception. We can't assert about what it does here, because that + // would involve capturing console output, which isn't safe in unit tests. Instead + // we'll check this in E2E tests. + EntrypointInvoker.InvokeEntrypoint(assembly.FullName, new string[] { }); + Assert.True(didMainExecute()); + } + + [Fact] + public void InvokesEntrypoint_Async_Exception() + { + // Arrange + var assembly = CompileToAssembly(@" +public static TaskCompletionSource<object> ContinueTcs { get; } = new TaskCompletionSource<object>(); + +public static async Task Main() +{ + await ContinueTcs.Task; + DidMainExecute = true; + throw new InvalidTimeZoneException(""Test message""); +}", out var didMainExecute); + + // Act/Assert 1: Waits for task + EntrypointInvoker.InvokeEntrypoint(assembly.FullName, new string[] { }); + Assert.False(didMainExecute()); + + // Act/Assert 2: Continues + // As above, we can't directly observe the exception handling behavior here, + // so this is covered in E2E tests instead. + var tcs = (TaskCompletionSource<object>)assembly.GetType("SomeApp.Program").GetProperty("ContinueTcs").GetValue(null); + tcs.SetResult(null); + Assert.True(didMainExecute()); + } + + private static Assembly CompileToAssembly(string mainMethod, out Func<bool> didMainExecute) + { + var syntaxTree = CSharpSyntaxTree.ParseText(@" +using System; +using System.Threading.Tasks; + +namespace SomeApp +{ + public static class Program + { + public static bool DidMainExecute { get; private set; } + + " + mainMethod + @" + } +}"); + + var compilation = CSharpCompilation.Create( + $"TestAssembly-{Guid.NewGuid().ToString("D")}", + new[] { syntaxTree }, + new[] { MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.ConsoleApplication)); + using var ms = new MemoryStream(); + var compilationResult = compilation.Emit(ms); + ms.Seek(0, SeekOrigin.Begin); + var assembly = AssemblyLoadContext.Default.LoadFromStream(ms); + + var didMainExecuteProp = assembly.GetType("SomeApp.Program").GetProperty("DidMainExecute"); + didMainExecute = () => (bool)didMainExecuteProp.GetValue(null); + + return assembly; + } + } +} diff --git a/src/Components/Blazor/Blazor/test/Microsoft.AspNetCore.Blazor.Tests.csproj b/src/Components/Blazor/Blazor/test/Microsoft.AspNetCore.Blazor.Tests.csproj index a0acf4173e60..be1cb3f836b7 100644 --- a/src/Components/Blazor/Blazor/test/Microsoft.AspNetCore.Blazor.Tests.csproj +++ b/src/Components/Blazor/Blazor/test/Microsoft.AspNetCore.Blazor.Tests.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> @@ -6,6 +6,7 @@ <ItemGroup> <Reference Include="Microsoft.AspNetCore.Blazor" /> + <Reference Include="Microsoft.CodeAnalysis.CSharp" /> </ItemGroup> </Project> diff --git a/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html b/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html index 5da6ba26b31b..fde34bd63924 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html +++ b/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> @@ -11,6 +11,12 @@ <body> <app>Loading...</app> + <div id="blazor-error-ui"> + An unhandled exception has occurred. See browser dev tools for details. + <a href="" class="reload">Reload</a> + <a class="dismiss">🗙</a> + </div> + <script src="_framework/blazor.webassembly.js"></script> </body> </html> diff --git a/src/Components/Components.sln b/src/Components/Components.sln index b4d18400258b..91278955cf7b 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -248,6 +248,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{F2E27E1C-2E47-42C1-9AC7-36265A381717}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1518,6 +1520,18 @@ Global {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.Build.0 = Release|Any CPU {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.ActiveCfg = Release|Any CPU {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.Build.0 = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x64.ActiveCfg = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x64.Build.0 = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x86.ActiveCfg = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x86.Build.0 = Debug|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|Any CPU.Build.0 = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x64.ActiveCfg = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x64.Build.0 = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.ActiveCfg = Release|Any CPU + {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1632,6 +1646,7 @@ Global {A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} + {F2E27E1C-2E47-42C1-9AC7-36265A381717} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE} diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index efecd016e9ef..1a800983017f 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -73,5 +73,7 @@ interface BootJsonData { window['Blazor'].start = boot; if (shouldAutoStart()) { - boot(); + boot().catch(error => { + Module.printErr(error); // Logs it, and causes the error UI to appear + }); } diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 31fee329d624..527dcd5ab8ae 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -11,8 +11,7 @@ let assembly_load: (assemblyName: string) => number; let find_class: (assemblyHandle: number, namespace: string, className: string) => number; let find_method: (typeHandle: number, methodName: string, unknownArg: number) => MethodHandle; let invoke_method: (method: MethodHandle, target: System_Object, argsArrayPtr: number, exceptionFlagIntPtr: number) => System_Object; -let mono_call_assembly_entry_point: (assemblyName: string, args: System_Object[]) => System_Object; -let mono_obj_array_new: (length: number) => System_Object; +let mono_string_array_new: (length: number) => System_Array<System_String>; let mono_string_get_utf8: (managedString: System_String) => Mono.Utf8Ptr; let mono_string: (jsString: string) => System_String; const appBinDirName = 'appBinDir'; @@ -41,9 +40,18 @@ export const monoPlatform: Platform = { findMethod: findMethod, - callEntryPoint: function callEntryPoint(assemblyName: string): System_Object { - const empty_array = mono_obj_array_new(0); - return mono_call_assembly_entry_point(assemblyName, [empty_array]); + callEntryPoint: function callEntryPoint(assemblyName: string) { + // Instead of using Module.mono_call_assembly_entry_point, we have our own logic for invoking + // the entrypoint which adds support for async main. + // Currently we disregard the return value from the entrypoint, whether it's sync or async. + // In the future, we might want Blazor.start to return a Promise<Promise<value>>, where the + // outer promise reflects the startup process, and the inner one reflects the possibly-async + // .NET entrypoint method. + const invokeEntrypoint = findMethod('Microsoft.AspNetCore.Blazor', 'Microsoft.AspNetCore.Blazor.Hosting', 'EntrypointInvoker', 'InvokeEntrypoint'); + this.callMethod(invokeEntrypoint, null, [ + this.toDotNetString(assemblyName), + mono_string_array_new(0) // In the future, we may have a way of supplying arg strings. For now, we always supply an empty string[]. + ]); }, callMethod: function callMethod(method: MethodHandle, target: System_Object, args: System_Object[]): System_Object { @@ -263,11 +271,9 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () 'number', ]); - mono_call_assembly_entry_point = Module.mono_call_assembly_entry_point; - mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']); mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); - mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']); + mono_string_array_new = Module.cwrap('mono_wasm_string_array_new', 'number', ['number']); MONO.loaded_files = []; diff --git a/src/Components/Web.JS/src/Platform/Platform.ts b/src/Components/Web.JS/src/Platform/Platform.ts index 84587f943a1b..29eb04609e7a 100644 --- a/src/Components/Web.JS/src/Platform/Platform.ts +++ b/src/Components/Web.JS/src/Platform/Platform.ts @@ -1,7 +1,7 @@ export interface Platform { start(loadAssemblyUrls: string[]): Promise<void>; - callEntryPoint(assemblyName: string): System_Object; + callEntryPoint(assemblyName: string): void; findMethod(assemblyName: string, namespace: string, className: string, methodName: string): MethodHandle; callMethod(method: MethodHandle, target: System_Object | null, args: (System_Object | null)[]): System_Object; diff --git a/src/Components/test/E2ETest/Tests/ErrorNotificationServerSideTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerErrorNotificationTest.cs similarity index 85% rename from src/Components/test/E2ETest/Tests/ErrorNotificationServerSideTest.cs rename to src/Components/test/E2ETest/ServerExecutionTests/ServerErrorNotificationTest.cs index 6d2e86057375..77b7da75d65a 100644 --- a/src/Components/test/E2ETest/Tests/ErrorNotificationServerSideTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerErrorNotificationTest.cs @@ -5,16 +5,15 @@ using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests; using Microsoft.AspNetCore.E2ETesting; -using OpenQA.Selenium; using Xunit; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Components.E2ETest.Tests { [Collection("ErrorNotification")] // When the clientside and serverside tests run together it seems to cause failures, possibly due to connection lose on exception. - public class ErrorNotificationServerSideTest : ErrorNotificationClientSideTest + public class ServerErrorNotificationTest : ErrorNotificationTest { - public ErrorNotificationServerSideTest( + public ServerErrorNotificationTest( BrowserFixture browserFixture, ToggleExecutionModeServerFixture<Program> serverFixture, ITestOutputHelper output) diff --git a/src/Components/test/E2ETest/Tests/ErrorNotificationClientSideTest.cs b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs similarity index 94% rename from src/Components/test/E2ETest/Tests/ErrorNotificationClientSideTest.cs rename to src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs index 7c0705acdefd..883d1bc5ab21 100644 --- a/src/Components/test/E2ETest/Tests/ErrorNotificationClientSideTest.cs +++ b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs @@ -13,9 +13,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests { [Collection("ErrorNotification")] // When the clientside and serverside tests run together it seems to cause failures, possibly due to connection lose on exception. - public class ErrorNotificationClientSideTest : ServerTestBase<ToggleExecutionModeServerFixture<Program>> + public class ErrorNotificationTest : ServerTestBase<ToggleExecutionModeServerFixture<Program>> { - public ErrorNotificationClientSideTest( + public ErrorNotificationTest( BrowserFixture browserFixture, ToggleExecutionModeServerFixture<Program> serverFixture, ITestOutputHelper output) diff --git a/src/Components/test/E2ETest/Tests/StartupErrorNotificationTest.cs b/src/Components/test/E2ETest/Tests/StartupErrorNotificationTest.cs new file mode 100644 index 000000000000..75359253c0a5 --- /dev/null +++ b/src/Components/test/E2ETest/Tests/StartupErrorNotificationTest.cs @@ -0,0 +1,40 @@ +// 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 BasicTestApp; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using OpenQA.Selenium; +using Xunit.Abstractions; +using Xunit; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests +{ + public class StartupErrorNotificationTest : ServerTestBase<DevHostServerFixture<Program>> + { + public StartupErrorNotificationTest( + BrowserFixture browserFixture, + DevHostServerFixture<Program> serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + _serverFixture.PathBase = ServerPathBase; + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void DisplaysNotificationForStartupException(bool errorIsAsync) + { + var url = $"{ServerPathBase}?error={(errorIsAsync ? "async" : "sync")}"; + + Navigate(url, noReload: true); + var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10)); + Assert.NotNull(errorUiElem); + + Browser.Equal("block", () => errorUiElem.GetCssValue("display")); + } + } +} diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor index 0548f382a898..eff29276a459 100644 --- a/src/Components/test/testassets/BasicTestApp/Index.razor +++ b/src/Components/test/testassets/BasicTestApp/Index.razor @@ -87,12 +87,6 @@ @((RenderFragment)RenderSelectedComponent) </app> -<div id="blazor-error-ui"> - An unhandled error has occurred. - <a href class='reload'>Reload</a> - <a class='dismiss' style="cursor: pointer;">🗙</a> -</div> - @code { string SelectedComponentTypeName { get; set; } = "none"; diff --git a/src/Components/test/testassets/BasicTestApp/Program.cs b/src/Components/test/testassets/BasicTestApp/Program.cs index cebb226e7c46..2be7d81b4e2d 100644 --- a/src/Components/test/testassets/BasicTestApp/Program.cs +++ b/src/Components/test/testassets/BasicTestApp/Program.cs @@ -1,15 +1,20 @@ // 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.Globalization; +using System.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Hosting; +using Mono.WebAssembly.Interop; namespace BasicTestApp { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { + await SimulateErrorsIfNeededForTest(); + // We want the culture to be en-US so that the tests for bind can work consistently. CultureInfo.CurrentCulture = new CultureInfo("en-US"); @@ -19,5 +24,22 @@ public static void Main(string[] args) public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => BlazorWebAssemblyHost.CreateDefaultBuilder() .UseBlazorStartup<Startup>(); + + // Supports E2E tests in StartupErrorNotificationTest + private static async Task SimulateErrorsIfNeededForTest() + { + var currentUrl = new MonoWebAssemblyJSRuntime().Invoke<string>("getCurrentUrl"); + if (currentUrl.Contains("error=sync")) + { + throw new InvalidTimeZoneException("This is a synchronous startup exception"); + } + + await Task.Yield(); + + if (currentUrl.Contains("error=async")) + { + throw new InvalidTimeZoneException("This is an asynchronous startup exception"); + } + } } } diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/index.html b/src/Components/test/testassets/BasicTestApp/wwwroot/index.html index 517d9d6fcc10..a37c08a7d1a2 100644 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/index.html +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/index.html @@ -14,6 +14,13 @@ <body> <root>Loading...</root> + <!-- Explicit display:none required so StartupErrorNotificationTest can observe it change --> + <div id="blazor-error-ui" style="display: none;"> + An unhandled error has occurred. + <a href class='reload'>Reload</a> + <a class='dismiss' style="cursor: pointer;">🗙</a> + </div> + <!-- Used for testing interop scenarios between JS and .NET --> <script src="js/jsinteroptests.js"></script> @@ -27,6 +34,10 @@ function navigationManagerNavigate() { Blazor.navigateTo('/subdir/some-path'); } + + function getCurrentUrl() { + return location.href; + } </script> <script src="_framework/blazor.webassembly.js"></script> diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/style.css b/src/Components/test/testassets/BasicTestApp/wwwroot/style.css index 777375d9e0e2..ea9900430b1c 100644 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/style.css +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/style.css @@ -7,11 +7,23 @@ } #blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; + box-sizing: border-box; } - #blazor-error-ui dismiss { + #blazor-error-ui .dismiss { cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; } .validation-message { diff --git a/src/Components/test/testassets/TestServer/Pages/_ServerHost.cshtml b/src/Components/test/testassets/TestServer/Pages/_ServerHost.cshtml index af2f28f65854..b0ba837af22b 100644 --- a/src/Components/test/testassets/TestServer/Pages/_ServerHost.cshtml +++ b/src/Components/test/testassets/TestServer/Pages/_ServerHost.cshtml @@ -17,6 +17,12 @@ <!-- Used for testing interop scenarios between JS and .NET --> <script src="js/jsinteroptests.js"></script> + <div id="blazor-error-ui"> + An unhandled error has occurred. + <a href class='reload'>Reload</a> + <a class='dismiss' style="cursor: pointer;">🗙</a> + </div> + <script> // Used by ElementRefComponent function setElementValue(element, newValue) { From e4c0ec3ca6128dd6161a53bb55c66ea8396cac42 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson <jacalvar@microsoft.com> Date: Fri, 13 Dec 2019 14:36:52 +0100 Subject: [PATCH 034/322] [Blazor] Update branding for the next release (#17852) --- src/Components/Blazor/Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props index 9e35475c8610..59beb90ee9d8 100644 --- a/src/Components/Blazor/Directory.Build.props +++ b/src/Components/Blazor/Directory.Build.props @@ -3,8 +3,8 @@ <PropertyGroup> <!-- Override version labels --> - <VersionPrefix>3.1.0</VersionPrefix> - <PreReleaseVersionLabel>preview4</PreReleaseVersionLabel> + <VersionPrefix>3.2.0</VersionPrefix> + <PreReleaseVersionLabel>preview1</PreReleaseVersionLabel> <DotNetFinalVersionKind /> <!-- This property points to the latest released Microsoft.AspNetCore.App version it needs to be updated to target the latest patch before a preview release. --> From b0568d5c28a22875e2452e7e52f5eae64b53aeeb Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 17 Dec 2019 11:48:08 -0800 Subject: [PATCH 035/322] Revive build installers step (#17914) * Revive build installers step --- .azure/pipelines/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 926e0b934a5d..064ad0327bcb 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -117,6 +117,19 @@ stages: $(_BuildArgs) displayName: Code sign packages + # Windows installers bundle both x86 and x64 assets + - script: ./build.cmd + -ci + -sign + -buildInstallers + /bl:artifacts/log/installers.msbuild.binlog + /p:DotNetSignType=$(_SignType) + /p:AssetManifestFileName=aspnetcore-win-x64-x86.xml + $(_BuildArgs) + $(_PublishArgs) + /p:PublishInstallerBaseVersion=true + displayName: Build Installers + artifacts: - name: Windows_Logs path: artifacts/log/ From 62e2fb22e5eef6ba4be0919a2f0d9435293eac82 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Wed, 18 Dec 2019 12:18:18 -0800 Subject: [PATCH 036/322] Use mono_bind_static_method for invoking JS methods (#17942) * Use mono_bind_static_method for invoking JS methods --- .../Blazor/src/Hosting/EntrypointInvoker.cs | 2 +- .../Web.JS/dist/Release/blazor.server.js | 2 +- .../Web.JS/dist/Release/blazor.webassembly.js | 2 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 156 +++--------------- .../Web.JS/src/Platform/Mono/MonoTypes.d.ts | 6 +- .../Web.JS/src/Platform/Platform.ts | 4 - 6 files changed, 35 insertions(+), 137 deletions(-) diff --git a/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs b/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs index bce063bcf56f..40a5d07de431 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/EntrypointInvoker.cs @@ -22,7 +22,7 @@ public static void InvokeEntrypoint(string assemblyName, string[] args) { var assembly = Assembly.Load(assemblyName); var entrypoint = FindUnderlyingEntrypoint(assembly); - var @params = entrypoint.GetParameters().Length == 1 ? new object[] { args } : new object[] { }; + var @params = entrypoint.GetParameters().Length == 1 ? new object[] { args ?? Array.Empty<string>() } : new object[] { }; entrypointResult = entrypoint.Invoke(null, @params); } catch (Exception syncException) diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index e3ada49ef785..36050055b123 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -12,4 +12,4 @@ var r=n(50),o=n(51),i=n(52);function a(){return c.TYPED_ARRAY_SUPPORT?2147483647 * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ -function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0}function o(e){return t.Buffer&&"function"==typeof t.Buffer.isBuffer?t.Buffer.isBuffer(e):!(null==e||!e._isBuffer)}var i=n(34),a=Object.prototype.hasOwnProperty,s=Array.prototype.slice,c="foo"===function(){}.name;function u(e){return Object.prototype.toString.call(e)}function l(e){return!o(e)&&("function"==typeof t.ArrayBuffer&&("function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(e):!!e&&(e instanceof DataView||!!(e.buffer&&e.buffer instanceof ArrayBuffer))))}var f=e.exports=v,h=/\s*function\s+([^\(\s]*)\s*/;function p(e){if(i.isFunction(e)){if(c)return e.name;var t=e.toString().match(h);return t&&t[1]}}function d(e,t){return"string"==typeof e?e.length<t?e:e.slice(0,t):e}function g(e){if(c||!i.isFunction(e))return i.inspect(e);var t=p(e);return"[Function"+(t?": "+t:"")+"]"}function y(e,t,n,r,o){throw new f.AssertionError({message:n,actual:e,expected:t,operator:r,stackStartFunction:o})}function v(e,t){e||y(e,!0,t,"==",f.ok)}function b(e,t,n,a){if(e===t)return!0;if(o(e)&&o(t))return 0===r(e,t);if(i.isDate(e)&&i.isDate(t))return e.getTime()===t.getTime();if(i.isRegExp(e)&&i.isRegExp(t))return e.source===t.source&&e.global===t.global&&e.multiline===t.multiline&&e.lastIndex===t.lastIndex&&e.ignoreCase===t.ignoreCase;if(null!==e&&"object"==typeof e||null!==t&&"object"==typeof t){if(l(e)&&l(t)&&u(e)===u(t)&&!(e instanceof Float32Array||e instanceof Float64Array))return 0===r(new Uint8Array(e.buffer),new Uint8Array(t.buffer));if(o(e)!==o(t))return!1;var c=(a=a||{actual:[],expected:[]}).actual.indexOf(e);return-1!==c&&c===a.expected.indexOf(t)||(a.actual.push(e),a.expected.push(t),function(e,t,n,r){if(null==e||null==t)return!1;if(i.isPrimitive(e)||i.isPrimitive(t))return e===t;if(n&&Object.getPrototypeOf(e)!==Object.getPrototypeOf(t))return!1;var o=m(e),a=m(t);if(o&&!a||!o&&a)return!1;if(o)return e=s.call(e),t=s.call(t),b(e,t,n);var c,u,l=S(e),f=S(t);if(l.length!==f.length)return!1;for(l.sort(),f.sort(),u=l.length-1;u>=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return u[c]=o,r(c),c++},h.clearImmediate=p}function p(e){delete u[e]}function d(e){if(l)setTimeout(d,0,e);else{var t=u[e];if(t){l=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{p(e),l=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(9),n(20))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(9))},function(e,t,n){"use strict";var r=n(66).Transform,o=n(15),i=n(22);function a(e){(e=e||{}).objectMode=!0,e.highWaterMark=16,r.call(this,e),this._msgpack=e.msgpack}function s(e){if(!(this instanceof s))return(e=e||{}).msgpack=this,new s(e);a.call(this,e)}function c(e){if(!(this instanceof c))return(e=e||{}).msgpack=this,new c(e);a.call(this,e),this._chunks=i()}o(a,r),o(s,a),s.prototype._transform=function(e,t,n){var r=null;try{r=this._msgpack.encode(e).slice(0)}catch(e){return this.emit("error",e),n()}this.push(r),n()},o(c,a),c.prototype._transform=function(e,t,n){e&&this._chunks.append(e);try{var r=this._msgpack.decode(this._chunks);this.push(r)}catch(e){return void(e instanceof this._msgpack.IncompleteBufferError?n():this.emit("error",e))}this._chunks.length>0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(34).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t<n)}(h,o))return null;switch(h){case 192:return n(null,1);case 194:return n(!1,1);case 195:return n(!0,1);case 204:return n(p=e.readUInt8(r+1),2);case 205:return n(p=e.readUInt16BE(r+1),3);case 206:return n(p=e.readUInt32BE(r+1),5);case 207:for(f=7;f>=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;s.push(u.value),t+=u.bytesConsumed,c+=u.bytesConsumed}return n(s,o+c)}function s(e,t,r,o){var a,s={},c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;var l=i(e,t+=u.bytesConsumed);if(!l)return null;s[u.value]=l.value,t+=l.bytesConsumed,c+=u.bytesConsumed+l.bytesConsumed}return n(s,o+c)}function c(e,t,n){var r=e.readInt8(t+1);return u(e,t,r,n,2)}function u(t,r,o,i,a){var s,c;if(r+=a,o<0)switch(o){case-1:return function(e,t,r){var o,i;switch(i=0,t){case 4:o=e.readUInt32BE(0);break;case 8:var a=e.readUInt32BE(0),s=e.readUInt32BE(4);i=a/4,o=(3&a)*Math.pow(2,32)+s;break;case 12:throw new Error("timestamp 96 is not yet implemented")}var c=1e3*o+Math.round(i/1e6);return n(new Date(c),t+r)}(c=t.slice(r,r+i),i,a)}for(s=0;s<e.length;s++){if(o===e[s].type)return c=t.slice(r,r+i),n(e[s].decode(c),a+i)}throw new Error("unable to find ext type "+o)}},e.exports.IncompleteBufferError=o},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(22),i=.1;function a(e,t){var n;return(n=r.allocUnsafe(5))[0]=202,n.writeFloatBE(e,1),(t||Math.abs(e-n.readFloatBE(1))>i)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n<e.length;n++)if(e[n].check(t)){i=e[n].encode(t);break}if(!i)return null;1==(a=i.length-1)?s.push(212):2===a?s.push(213):4===a?s.push(214):8===a?s.push(215):16===a?s.push(216):a<256?(s.push(199),s.push(a)):a<65536?(s.push(200),s.push(a>>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(5),a=n(71),s=n(16),c=function(){function e(e,t){this.nextBatchId=2,this.browserRendererId=e,this.logger=t}return e.getOrCreate=function(t){return e.instance||(e.instance=new e(0,t)),this.instance},e.prototype.processBatch=function(e,t,n){return r(this,void 0,void 0,function(){var r;return o(this,function(o){switch(o.label){case 0:return e<this.nextBatchId?[4,this.completeBatch(n,e)]:[3,2];case 1:return o.sent(),this.logger.log(s.LogLevel.Debug,"Batch "+e+" already processed. Waiting for batch "+this.nextBatchId+"."),[2];case 2:return e>this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<<r,i<128)break;r+=7}return n}(this.batchDataUint8,n),i=n+((t=o)<128?1:t<16384?2:t<2097152?3:4),a=new Uint8Array(this.batchDataUint8.buffer,this.batchDataUint8.byteOffset+i,o);return r.decodeUtf8(a)},e}(),f=function(){function e(e){this.batchDataUint8=e}return e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}(),h=function(){function e(e){this.batchDataUint8=e}return e.prototype.offset=function(e){return 0},e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}();function p(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function d(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t<n;){var i=e[t++];if(0===i)break;if(0==(128&i))r.push(i);else if(192==(224&i)){var a=63&e[t++];r.push((31&i)<<6|a)}else if(224==(240&i)){var a=63&e[t++],s=63&e[t++];r.push((31&i)<<12|a<<6|s)}else if(240==(248&i)){var a=63&e[t++],s=63&e[t++],c=63&e[t++],u=(7&i)<<18|a<<12|s<<6|c;u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(12),a=n(13),s=function(){function e(e){this.circuitId=void 0,this.components=e}return e.prototype.reconnect=function(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.invoke("ConnectCircuit",this.circuitId)},e.prototype.initialize=function(e){if(this.circuitId)throw new Error("Circuit host '"+this.circuitId+"' already initialized.");this.circuitId=e},e.prototype.startCircuit=function(e){return r(this,void 0,void 0,function(){var t;return o(this,function(n){switch(n.label){case 0:return[4,e.invoke("StartCircuit",i.internalFunctions.getBaseURI(),i.internalFunctions.getLocationHref(),JSON.stringify(this.components.map(function(e){return e.toRecord()})))];case 1:return(t=n.sent())?(this.initialize(t),[2,!0]):[2,!1]}})})},e.prototype.resolveElement=function(e){var t=Number.parseInt(e);if(Number.isNaN(t))throw new Error("Invalid sequence number '"+e+"'.");return a.toLogicalRootCommentElement(this.components[t].start,this.components[t].end)},e}();t.CircuitDescriptor=s;var c=function(){function e(e,t,n,r,o){this.type=e,this.start=t,this.end=n,this.sequence=r,this.descriptor=o}return e.prototype.toRecord=function(){return{type:this.type,sequence:this.sequence,descriptor:this.descriptor}},e}();t.ComponentDescriptor=c,t.discoverComponents=function(e){for(var t=function e(t){if(!t.hasChildNodes())return[];for(var n=[],r=new h(t.childNodes);r.next()&&r.currentElement;){var o=l(r);if(o)n.push(o);else for(var i=e(r.currentElement),a=0;a<i.length;a++){var s=i[a];n.push(s)}}return n}(e),n=[],r=0;r<t.length;r++){var o=t[r],i=new c(o.type,o.start,o.end,o.sequence,o.descriptor);n.push(i)}return n.sort(function(e,t){return e.sequence-t.sequence})};var u=/\W*Blazor:[^{]*(.*)$/;function l(e){var t=e.currentElement;if(t&&t.nodeType===Node.COMMENT_NODE&&t.textContent){var n=new RegExp(u).exec(t.textContent),r=n&&n[1];if(!r)return;try{return function(e,t,n){var r=JSON.parse(e),o=r.type,i=r.sequence,a=r.descriptor,s=r.prerenderId;if("server"!==o)throw new Error("Invalid component type '"+o+"'.");if(!a)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===i)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(i))throw new Error("Error parsing the sequence '"+i+"' for component '"+e+"'");if(s){var c=function(e,t){for(;t.next()&&t.currentElement;){var n=t.currentElement;if(n.nodeType===Node.COMMENT_NODE&&n.textContent){var r=new RegExp(u).exec(n.textContent),o=r&&r[1];if(o)return f(o,e),n}}return}(s,n);if(!c)throw new Error("Could not find an end component comment for '"+t+"'");return{type:o,sequence:i,descriptor:a,start:t,prerenderId:s,end:c}}return{type:o,sequence:i,descriptor:a,start:t}}(r,t,e)}catch(e){throw new Error("Found malformed component comment at "+t.textContent)}}}function f(e,t){var n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error("Invalid end of component comment: '"+e+"'");var r=n.prerenderId;if(!r)throw new Error("End of component comment must have a value for the prerendered property: '"+e+"'");if(r!==t)throw new Error("End of component comment prerendered property must match the start comment prerender id: '"+t+"', '"+r+"'")}var h=function(){function e(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}return e.prototype.next=function(){return this.currentIndex++,this.currentIndex<this.length?(this.currentElement=this.childNodes[this.currentIndex],!0):(this.currentElement=void 0,!1)},e}()},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=n(16);t.resolveOptions=function(e){var t=r({},i,e);return e&&e.reconnectionOptions&&(t.reconnectionOptions=r({},i.reconnectionOptions,e.reconnectionOptions)),t};var i={configureSignalR:function(e){},logLevel:o.LogLevel.Warning,reconnectionOptions:{maxRetries:5,retryIntervalMilliseconds:3e3,dialogId:"components-reconnect-modal"}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(77),a=n(78),s=n(16),c=function(){function e(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||function(){return window.Blazor.reconnect()}}return e.prototype.onConnectionDown=function(e,t){if(!this._reconnectionDisplay){var n=document.getElementById(e.dialogId);this._reconnectionDisplay=n?new a.UserSpecifiedDisplay(n):new i.DefaultReconnectDisplay(e.dialogId,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new u(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))},e.prototype.onConnectionUp=function(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)},e}();t.DefaultReconnectionHandler=c;var u=function(){function e(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}return e.prototype.dispose=function(){this.isDisposed=!0,this.reconnectDisplay.hide()},e.prototype.attemptPeriodicReconnection=function(e){return r(this,void 0,void 0,function(){var t,n;return o(this,function(r){switch(r.label){case 0:t=0,r.label=1;case 1:return t<e.maxRetries?[4,this.delay(e.retryIntervalMilliseconds)]:[3,7];case 2:if(r.sent(),this.isDisposed)return[3,7];r.label=3;case 3:return r.trys.push([3,5,,6]),[4,this.reconnectCallback()];case 4:return r.sent()?[2]:(this.reconnectDisplay.rejected(),[2]);case 5:return n=r.sent(),this.logger.log(s.LogLevel.Error,n),[3,6];case 6:return t++,[3,1];case 7:return this.reconnectDisplay.failed(),[2]}})})},e.prototype.delay=function(e){return new Promise(function(t){return setTimeout(t,e)})},e}()},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(16),a=function(){function e(e,t,n){var a=this;this.document=t,this.logger=n,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry</button><p>Alternatively, <a href>reload</a></p>',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.button.addEventListener("click",function(){return r(a,void 0,void 0,function(){var e;return o(this,function(t){switch(t.label){case 0:this.show(),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,window.Blazor.reconnect()];case 2:return t.sent()||this.rejected(),[3,4];case 3:return e=t.sent(),this.logger.log(i.LogLevel.Error,e),this.failed(),[3,4];case 4:return[2]}})})}),this.reloadParagraph.querySelector("a").addEventListener("click",function(){return location.reload()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.message.innerHTML="Reconnection failed. Try <a href>reloading</a> the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o<e.byteLength;){var i=0,a=0,s=void 0;do{a|=(127&(s=n[o+i]))<<r[i],i++}while(i<Math.min(5,e.byteLength-o)&&0!=(128&s));if(0!=(128&s)&&i<5)throw new Error("Cannot read message size.");if(5===i&&s>7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s<c.length;s++){var u=c[s],l=this.parseMessage(u,t);l&&o.push(l)}return o},e.prototype.writeMessage=function(e){switch(e.type){case i.MessageType.Invocation:return this.writeInvocation(e);case i.MessageType.StreamInvocation:return this.writeStreamInvocation(e);case i.MessageType.StreamItem:return this.writeStreamItem(e);case i.MessageType.Completion:return this.writeCompletion(e);case i.MessageType.Ping:return a.write(s);case i.MessageType.CancelInvocation:return this.writeCancelInvocation(e);default:throw new Error("Invalid message type.")}},e.prototype.parseMessage=function(e,t){if(0===e.length)throw new Error("Invalid payload.");var n=o().decode(r.Buffer.from(e));if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");var a=n[0];switch(a){case i.MessageType.Invocation:return this.createInvocationMessage(this.readHeaders(n),n);case i.MessageType.StreamItem:return this.createStreamItemMessage(this.readHeaders(n),n);case i.MessageType.Completion:return this.createCompletionMessage(this.readHeaders(n),n);case i.MessageType.Ping:return this.createPingMessage(n);case i.MessageType.Close:return this.createCloseMessage(n);default:return t.log(i.LogLevel.Information,"Unknown message type '"+a+"' ignored."),null}},e.prototype.createCloseMessage=function(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="0.0.0-DEV_BUILD"}]); \ No newline at end of file +function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0}function o(e){return t.Buffer&&"function"==typeof t.Buffer.isBuffer?t.Buffer.isBuffer(e):!(null==e||!e._isBuffer)}var i=n(34),a=Object.prototype.hasOwnProperty,s=Array.prototype.slice,c="foo"===function(){}.name;function u(e){return Object.prototype.toString.call(e)}function l(e){return!o(e)&&("function"==typeof t.ArrayBuffer&&("function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(e):!!e&&(e instanceof DataView||!!(e.buffer&&e.buffer instanceof ArrayBuffer))))}var f=e.exports=v,h=/\s*function\s+([^\(\s]*)\s*/;function p(e){if(i.isFunction(e)){if(c)return e.name;var t=e.toString().match(h);return t&&t[1]}}function d(e,t){return"string"==typeof e?e.length<t?e:e.slice(0,t):e}function g(e){if(c||!i.isFunction(e))return i.inspect(e);var t=p(e);return"[Function"+(t?": "+t:"")+"]"}function y(e,t,n,r,o){throw new f.AssertionError({message:n,actual:e,expected:t,operator:r,stackStartFunction:o})}function v(e,t){e||y(e,!0,t,"==",f.ok)}function b(e,t,n,a){if(e===t)return!0;if(o(e)&&o(t))return 0===r(e,t);if(i.isDate(e)&&i.isDate(t))return e.getTime()===t.getTime();if(i.isRegExp(e)&&i.isRegExp(t))return e.source===t.source&&e.global===t.global&&e.multiline===t.multiline&&e.lastIndex===t.lastIndex&&e.ignoreCase===t.ignoreCase;if(null!==e&&"object"==typeof e||null!==t&&"object"==typeof t){if(l(e)&&l(t)&&u(e)===u(t)&&!(e instanceof Float32Array||e instanceof Float64Array))return 0===r(new Uint8Array(e.buffer),new Uint8Array(t.buffer));if(o(e)!==o(t))return!1;var c=(a=a||{actual:[],expected:[]}).actual.indexOf(e);return-1!==c&&c===a.expected.indexOf(t)||(a.actual.push(e),a.expected.push(t),function(e,t,n,r){if(null==e||null==t)return!1;if(i.isPrimitive(e)||i.isPrimitive(t))return e===t;if(n&&Object.getPrototypeOf(e)!==Object.getPrototypeOf(t))return!1;var o=m(e),a=m(t);if(o&&!a||!o&&a)return!1;if(o)return e=s.call(e),t=s.call(t),b(e,t,n);var c,u,l=S(e),f=S(t);if(l.length!==f.length)return!1;for(l.sort(),f.sort(),u=l.length-1;u>=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return u[c]=o,r(c),c++},h.clearImmediate=p}function p(e){delete u[e]}function d(e){if(l)setTimeout(d,0,e);else{var t=u[e];if(t){l=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{p(e),l=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(9),n(20))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(9))},function(e,t,n){"use strict";var r=n(66).Transform,o=n(15),i=n(22);function a(e){(e=e||{}).objectMode=!0,e.highWaterMark=16,r.call(this,e),this._msgpack=e.msgpack}function s(e){if(!(this instanceof s))return(e=e||{}).msgpack=this,new s(e);a.call(this,e)}function c(e){if(!(this instanceof c))return(e=e||{}).msgpack=this,new c(e);a.call(this,e),this._chunks=i()}o(a,r),o(s,a),s.prototype._transform=function(e,t,n){var r=null;try{r=this._msgpack.encode(e).slice(0)}catch(e){return this.emit("error",e),n()}this.push(r),n()},o(c,a),c.prototype._transform=function(e,t,n){e&&this._chunks.append(e);try{var r=this._msgpack.decode(this._chunks);this.push(r)}catch(e){return void(e instanceof this._msgpack.IncompleteBufferError?n():this.emit("error",e))}this._chunks.length>0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(34).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t<n)}(h,o))return null;switch(h){case 192:return n(null,1);case 194:return n(!1,1);case 195:return n(!0,1);case 204:return n(p=e.readUInt8(r+1),2);case 205:return n(p=e.readUInt16BE(r+1),3);case 206:return n(p=e.readUInt32BE(r+1),5);case 207:for(f=7;f>=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;s.push(u.value),t+=u.bytesConsumed,c+=u.bytesConsumed}return n(s,o+c)}function s(e,t,r,o){var a,s={},c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;var l=i(e,t+=u.bytesConsumed);if(!l)return null;s[u.value]=l.value,t+=l.bytesConsumed,c+=u.bytesConsumed+l.bytesConsumed}return n(s,o+c)}function c(e,t,n){var r=e.readInt8(t+1);return u(e,t,r,n,2)}function u(t,r,o,i,a){var s,c;if(r+=a,o<0)switch(o){case-1:return function(e,t,r){var o,i;switch(i=0,t){case 4:o=e.readUInt32BE(0);break;case 8:var a=e.readUInt32BE(0),s=e.readUInt32BE(4);i=a/4,o=(3&a)*Math.pow(2,32)+s;break;case 12:throw new Error("timestamp 96 is not yet implemented")}var c=1e3*o+Math.round(i/1e6);return n(new Date(c),t+r)}(c=t.slice(r,r+i),i,a)}for(s=0;s<e.length;s++){if(o===e[s].type)return c=t.slice(r,r+i),n(e[s].decode(c),a+i)}throw new Error("unable to find ext type "+o)}},e.exports.IncompleteBufferError=o},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(22),i=.1;function a(e,t){var n;return(n=r.allocUnsafe(5))[0]=202,n.writeFloatBE(e,1),(t||Math.abs(e-n.readFloatBE(1))>i)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n<e.length;n++)if(e[n].check(t)){i=e[n].encode(t);break}if(!i)return null;1==(a=i.length-1)?s.push(212):2===a?s.push(213):4===a?s.push(214):8===a?s.push(215):16===a?s.push(216):a<256?(s.push(199),s.push(a)):a<65536?(s.push(200),s.push(a>>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(5),a=n(71),s=n(16),c=function(){function e(e,t){this.nextBatchId=2,this.browserRendererId=e,this.logger=t}return e.getOrCreate=function(t){return e.instance||(e.instance=new e(0,t)),this.instance},e.prototype.processBatch=function(e,t,n){return r(this,void 0,void 0,function(){var r;return o(this,function(o){switch(o.label){case 0:return e<this.nextBatchId?[4,this.completeBatch(n,e)]:[3,2];case 1:return o.sent(),this.logger.log(s.LogLevel.Debug,"Batch "+e+" already processed. Waiting for batch "+this.nextBatchId+"."),[2];case 2:return e>this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<<r,i<128)break;r+=7}return n}(this.batchDataUint8,n),i=n+((t=o)<128?1:t<16384?2:t<2097152?3:4),a=new Uint8Array(this.batchDataUint8.buffer,this.batchDataUint8.byteOffset+i,o);return r.decodeUtf8(a)},e}(),f=function(){function e(e){this.batchDataUint8=e}return e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}(),h=function(){function e(e){this.batchDataUint8=e}return e.prototype.offset=function(e){return 0},e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}();function p(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function d(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t<n;){var i=e[t++];if(0===i)break;if(0==(128&i))r.push(i);else if(192==(224&i)){var a=63&e[t++];r.push((31&i)<<6|a)}else if(224==(240&i)){var a=63&e[t++],s=63&e[t++];r.push((31&i)<<12|a<<6|s)}else if(240==(248&i)){var a=63&e[t++],s=63&e[t++],c=63&e[t++],u=(7&i)<<18|a<<12|s<<6|c;u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(12),a=n(13),s=function(){function e(e){this.circuitId=void 0,this.components=e}return e.prototype.reconnect=function(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.invoke("ConnectCircuit",this.circuitId)},e.prototype.initialize=function(e){if(this.circuitId)throw new Error("Circuit host '"+this.circuitId+"' already initialized.");this.circuitId=e},e.prototype.startCircuit=function(e){return r(this,void 0,void 0,function(){var t;return o(this,function(n){switch(n.label){case 0:return[4,e.invoke("StartCircuit",i.internalFunctions.getBaseURI(),i.internalFunctions.getLocationHref(),JSON.stringify(this.components.map(function(e){return e.toRecord()})))];case 1:return(t=n.sent())?(this.initialize(t),[2,!0]):[2,!1]}})})},e.prototype.resolveElement=function(e){var t=Number.parseInt(e);if(Number.isNaN(t))throw new Error("Invalid sequence number '"+e+"'.");return a.toLogicalRootCommentElement(this.components[t].start,this.components[t].end)},e}();t.CircuitDescriptor=s;var c=function(){function e(e,t,n,r,o){this.type=e,this.start=t,this.end=n,this.sequence=r,this.descriptor=o}return e.prototype.toRecord=function(){return{type:this.type,sequence:this.sequence,descriptor:this.descriptor}},e}();t.ComponentDescriptor=c,t.discoverComponents=function(e){for(var t=function e(t){if(!t.hasChildNodes())return[];for(var n=[],r=new h(t.childNodes);r.next()&&r.currentElement;){var o=l(r);if(o)n.push(o);else for(var i=e(r.currentElement),a=0;a<i.length;a++){var s=i[a];n.push(s)}}return n}(e),n=[],r=0;r<t.length;r++){var o=t[r],i=new c(o.type,o.start,o.end,o.sequence,o.descriptor);n.push(i)}return n.sort(function(e,t){return e.sequence-t.sequence})};var u=/\W*Blazor:[^{]*(.*)$/;function l(e){var t=e.currentElement;if(t&&t.nodeType===Node.COMMENT_NODE&&t.textContent){var n=new RegExp(u).exec(t.textContent),r=n&&n[1];if(!r)return;try{return function(e,t,n){var r=JSON.parse(e),o=r.type,i=r.sequence,a=r.descriptor,s=r.prerenderId;if("server"!==o)throw new Error("Invalid component type '"+o+"'.");if(!a)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===i)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(i))throw new Error("Error parsing the sequence '"+i+"' for component '"+e+"'");if(s){var c=function(e,t){for(;t.next()&&t.currentElement;){var n=t.currentElement;if(n.nodeType===Node.COMMENT_NODE&&n.textContent){var r=new RegExp(u).exec(n.textContent),o=r&&r[1];if(o)return f(o,e),n}}return}(s,n);if(!c)throw new Error("Could not find an end component comment for '"+t+"'");return{type:o,sequence:i,descriptor:a,start:t,prerenderId:s,end:c}}return{type:o,sequence:i,descriptor:a,start:t}}(r,t,e)}catch(e){throw new Error("Found malformed component comment at "+t.textContent)}}}function f(e,t){var n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error("Invalid end of component comment: '"+e+"'");var r=n.prerenderId;if(!r)throw new Error("End of component comment must have a value for the prerendered property: '"+e+"'");if(r!==t)throw new Error("End of component comment prerendered property must match the start comment prerender id: '"+t+"', '"+r+"'")}var h=function(){function e(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}return e.prototype.next=function(){return this.currentIndex++,this.currentIndex<this.length?(this.currentElement=this.childNodes[this.currentIndex],!0):(this.currentElement=void 0,!1)},e}()},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=n(16);t.resolveOptions=function(e){var t=r({},i,e);return e&&e.reconnectionOptions&&(t.reconnectionOptions=r({},i.reconnectionOptions,e.reconnectionOptions)),t};var i={configureSignalR:function(e){},logLevel:o.LogLevel.Warning,reconnectionOptions:{maxRetries:5,retryIntervalMilliseconds:3e3,dialogId:"components-reconnect-modal"}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(77),a=n(78),s=n(16),c=function(){function e(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||function(){return window.Blazor.reconnect()}}return e.prototype.onConnectionDown=function(e,t){if(!this._reconnectionDisplay){var n=document.getElementById(e.dialogId);this._reconnectionDisplay=n?new a.UserSpecifiedDisplay(n):new i.DefaultReconnectDisplay(e.dialogId,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new u(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))},e.prototype.onConnectionUp=function(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)},e}();t.DefaultReconnectionHandler=c;var u=function(){function e(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}return e.prototype.dispose=function(){this.isDisposed=!0,this.reconnectDisplay.hide()},e.prototype.attemptPeriodicReconnection=function(e){return r(this,void 0,void 0,function(){var t,n;return o(this,function(r){switch(r.label){case 0:t=0,r.label=1;case 1:return t<e.maxRetries?[4,this.delay(e.retryIntervalMilliseconds)]:[3,7];case 2:if(r.sent(),this.isDisposed)return[3,7];r.label=3;case 3:return r.trys.push([3,5,,6]),[4,this.reconnectCallback()];case 4:return r.sent()?[2]:(this.reconnectDisplay.rejected(),[2]);case 5:return n=r.sent(),this.logger.log(s.LogLevel.Error,n),[3,6];case 6:return t++,[3,1];case 7:return this.reconnectDisplay.failed(),[2]}})})},e.prototype.delay=function(e){return new Promise(function(t){return setTimeout(t,e)})},e}()},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(16),a=function(){function e(e,t,n){var a=this;this.document=t,this.logger=n,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry</button><p>Alternatively, <a href>reload</a></p>',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.button.addEventListener("click",function(){return r(a,void 0,void 0,function(){var e;return o(this,function(t){switch(t.label){case 0:this.show(),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,window.Blazor.reconnect()];case 2:return t.sent()||this.rejected(),[3,4];case 3:return e=t.sent(),this.logger.log(i.LogLevel.Error,e),this.failed(),[3,4];case 4:return[2]}})})}),this.reloadParagraph.querySelector("a").addEventListener("click",function(){return location.reload()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.message.innerHTML="Reconnection failed. Try <a href>reloading</a> the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o<e.byteLength;){var i=0,a=0,s=void 0;do{a|=(127&(s=n[o+i]))<<r[i],i++}while(i<Math.min(5,e.byteLength-o)&&0!=(128&s));if(0!=(128&s)&&i<5)throw new Error("Cannot read message size.");if(5===i&&s>7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s<c.length;s++){var u=c[s],l=this.parseMessage(u,t);l&&o.push(l)}return o},e.prototype.writeMessage=function(e){switch(e.type){case i.MessageType.Invocation:return this.writeInvocation(e);case i.MessageType.StreamInvocation:return this.writeStreamInvocation(e);case i.MessageType.StreamItem:return this.writeStreamItem(e);case i.MessageType.Completion:return this.writeCompletion(e);case i.MessageType.Ping:return a.write(s);case i.MessageType.CancelInvocation:return this.writeCancelInvocation(e);default:throw new Error("Invalid message type.")}},e.prototype.parseMessage=function(e,t){if(0===e.length)throw new Error("Invalid payload.");var n=o().decode(r.Buffer.from(e));if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");var a=n[0];switch(a){case i.MessageType.Invocation:return this.createInvocationMessage(this.readHeaders(n),n);case i.MessageType.StreamItem:return this.createStreamItemMessage(this.readHeaders(n),n);case i.MessageType.Completion:return this.createCompletionMessage(this.readHeaders(n),n);case i.MessageType.Ping:return this.createPingMessage(n);case i.MessageType.Close:return this.createCloseMessage(n);default:return t.log(i.LogLevel.Information,"Unknown message type '"+a+"' ignored."),null}},e.prototype.createCloseMessage=function(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="3.1.0"}]); \ No newline at end of file diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js index d125cc352fbe..9f9d6b369d76 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webassembly.js +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -1 +1 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f<u;f++){var p=t.updatedComponentsEntry(l,f),m=d.componentId(p),h=d.edits(p);n.updateComponent(t,m,h,c)}var v=t.disposedComponentIds(),y=r.values(v),g=r.count(v);for(f=0;f<g;f++)m=t.disposedComponentIdsEntry(y,f),n.disposeComponent(m);var b=t.disposedEventHandlerIds(),w=r.values(b),E=r.count(b);for(f=0;f<E;f++){var _=t.disposedEventHandlerIdsEntry(w,f);n.disposeEventHandler(_)}i&&(i=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){i=!0}},,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17);var a,i=n(5),l=!1,u=!1,s=null;function c(e,t){var n=p(e);if(!t&&m(n))d(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function d(e,t){i.resetScrollAfterNextBatch(),history.pushState(null,"",e),f(t)}function f(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return s?[4,s(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(a=a||document.createElement("a")).href=e,a.href}function m(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(s=e,u)return;u=!0,window.addEventListener("popstate",function(){return f(!1)})},enableNavigationInterception:function(){l=!0},navigateTo:c,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(l&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));m(r)&&(e.preventDefault(),d(r,!0))}}})},t.navigateTo=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),a=p("_blazorLogicalEnd");function i(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n<i.length){var l=i[n];l.parentNode.insertBefore(e,l),i.splice(n,0,a)}else f(e,t),i.push(a);a[o]=t,r in a||(a[r]=[])}function u(e){return e[o]||null}function s(e){return e[r]}function c(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function d(e){var t=s(u(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function f(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=d(t);n?n.parentNode.insertBefore(e,n):f(e,u(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=i(n,!0),l=s(r);return Array.from(n.childNodes).forEach(function(e){return l.push(e)}),e[o]=r,t&&(e[a]=t,i(t,!0)),i(e,!0)},t.toLogicalElement=i,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return l(n,e,t),n},t.insertLogicalChild=l,t.removeLogicalChild=function e(t,n){var r=s(t).splice(n,1)[0];if(r instanceof Comment)for(var o=s(r);o.length>0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return l(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return u(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,d(t));return null==n?null:JSON.stringify(n,h)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,d(n)))});e&&r.then(function(t){return s().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],h))},function(t){return s().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,f(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);c(parseInt(e),t,r)}};var m=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return l(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return u(null,e,this._id,t)},e.prototype.dispose=function(){u(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function h(e,t){return t instanceof m?t.serializeAsArg():t}i(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new m(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(12),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),a=n(13),i=n(31),l=n(19),u=n(12),s=document.createElement("template"),c=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},f={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var a={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};l.dispatchEvent(a,r.data)}(e,t.browserRendererId,n,r,o)}),u.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),f[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var i=f[t];if(i){var l=a.getLogicalSiblingEnd(i);delete f[t],l?function(e,t){var n=a.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=a.getLogicalChildrenArray(n),o=r.indexOf(e)+1,i=r.indexOf(t),l=o;l<=i;l++)a.removeLogicalChild(n,o);e.textContent="!"}(i,l):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(i)}var u=a.getClosestDomElement(o).ownerDocument,s=u&&u.activeElement;this.applyEdits(e,t,o,0,n,r),s instanceof HTMLElement&&u&&u.activeElement!==s&&s.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,i,l){for(var u,s=0,c=o,d=e.arrayBuilderSegmentReader,f=e.editReader,p=e.frameReader,m=d.values(i),h=d.offset(i),v=h+d.count(i),y=h;y<v;y++){var g=e.diffReader.editsEntry(m,y),b=f.editType(g);switch(b){case r.EditType.prependFrame:var w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);this.insertFrame(e,t,n,c+_,l,E,w);break;case r.EditType.removeFrame:_=f.siblingIndex(g);a.removeLogicalChild(n,c+_);break;case r.EditType.setAttribute:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,I,E);break;case r.EditType.removeAttribute:var I;_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var S=f.removedAttributeName(g);this.tryApplySpecialProperty(e,I,S,null)||I.removeAttribute(S);break;case r.EditType.updateText:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);var C=a.getLogicalChild(n,c+_);if(!(C instanceof Text))throw new Error("Cannot set text content on non-text child");C.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);a.removeLogicalChild(n,c+_),this.insertMarkup(e,n,c+_,E);break;case r.EditType.stepIn:_=f.siblingIndex(g);n=a.getLogicalChild(n,c+_),s++,c=0;break;case r.EditType.stepOut:n=a.getLogicalParent(n),c=0===--s?o:0;break;case r.EditType.permutationListEntry:(u=u||[]).push({fromSiblingIndex:c+f.siblingIndex(g),toSiblingIndex:c+f.moveToSiblingIndex(g)});break;case r.EditType.permutationListEnd:a.permuteLogicalChildren(n,u),u=void 0;break;default:throw new Error("Unknown edit type: "+b)}}},e.prototype.insertFrame=function(e,t,n,o,a,l,u){var s=e.frameReader,c=s.frameType(l);switch(c){case r.FrameType.element:return this.insertElement(e,t,n,o,a,l,u),1;case r.FrameType.text:return this.insertText(e,n,o,l),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,l),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,a,u+1,u+s.subtreeLength(l));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return i.applyCaptureIdToElement(n,s.elementReferenceCaptureId(l)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,l),1;default:throw new Error("Unknown frame type: "+c)}},e.prototype.insertElement=function(e,t,n,o,i,l,u){var s=e.frameReader,c=s.elementName(l),d="svg"===c||a.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",c):document.createElement(c),f=a.toLogicalElement(d);a.insertLogicalChild(d,n,o);for(var p=u+s.subtreeLength(l),m=u+1;m<p;m++){var h=e.referenceFramesEntry(i,m);if(s.frameType(h)!==r.FrameType.attribute){this.insertFrameRange(e,t,f,0,i,m,p);break}this.applyAttribute(e,t,d,h)}if(d instanceof HTMLSelectElement&&"_blazorSelectValue"in d){var v=d._blazorSelectValue;d.value=v,delete d._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=a.createAndInsertLogicalContainer(t,n),i=e.frameReader.componentId(r);this.attachComponentToElement(i,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),i=document.createTextNode(o);a.insertLogicalChild(i,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,i=a.createAndInsertLogicalContainer(t,n),l=e.frameReader.markupContent(r),u=(o=l,a.isSvgElement(t)?(c.innerHTML=o||" ",c):(s.innerHTML=o||" ",s.content)),d=0;u.firstChild;)a.insertLogicalChild(u.firstChild,i,d++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,a=o.attributeName(r),i=o.attributeEventHandlerId(r);if(i){var l=h(a);this.eventDelegator.setListener(n,l,i,t)}else this.tryApplySpecialProperty(e,n,a,r)||n.setAttribute(a,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var a=h(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,a,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");a=h(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,a,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var a=n?r.attributeValue(n):null;return t.value=a,"SELECT"===t.tagName&&(t._blazorSelectValue=a),!0;case"OPTION":(a=n?r.attributeValue(n):null)?t.setAttribute("value",a):t.removeAttribute("value");var i=this.findClosestAncestorSelectElement(t);return i&&"_blazorSelectValue"in i&&i._blazorSelectValue===a&&(this.tryApplyValueProperty(e,i,n),delete i._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,a,i){for(var l=r,u=a;u<i;u++){var s=e.referenceFramesEntry(o,u);r+=this.insertFrame(e,t,n,r,o,s,u),u+=m(e,s)}return r-l},e}();function m(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function h(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),a=c(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),i=c(["click","dblclick","mousedown","mousemove","mouseup"]),l=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new u(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{var i={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(i),o.setHandler(t,i)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,l=e.target,u=null,s=a.hasOwnProperty(e.type),c=!1;l;){var d=this.getEventHandlerInfosForElement(l,!1);if(d){var f=d.getHandler(e.type);if(f&&(t=l,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&i.hasOwnProperty(n)&&t.disabled))){u||(u=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(f.renderingComponentId,e);this.onEvent(e,f.eventHandlerId,u,p)}d.stopPropagation(e.type)&&(c=!0),d.preventDefault(e.type)&&e.preventDefault()}l=s||c?null:l.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new s:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=l;var u=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=a.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),s=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function c(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==i.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var l=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:l});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},a(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",a(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},a(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},a(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function a(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var i=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0});var a=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),a||(a=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,function(e,t,n){"use strict";function r(e){var t=e.substring(e.lastIndexOf("/")+1),n=t.indexOf("?");return n<0?t:t.substring(0,n)}Object.defineProperty(t,"__esModule",{value:!0}),t.getFileNameFromUrl=r,t.getAssemblyNameFromUrl=function(e){return r(e).replace(/\.dll$/,"")}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17),n(24);var a=n(18),i=n(46),l=n(5),u=n(48),s=n(33),c=n(19),d=!1;function f(e){return r(this,void 0,void 0,function(){var e,t,n,s,f=this;return o(this,function(m){switch(m.label){case 0:if(d)throw new Error("Blazor has already started.");return d=!0,c.setEventDispatcher(function(e,t){return DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","DispatchEvent",e,JSON.stringify(t))}),e=a.setPlatform(i.monoPlatform),window.Blazor.platform=e,window.Blazor._internal.renderBatch=function(e,t){l.renderBatch(e,new u.SharedMemoryRenderBatch(t))},window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return r(f,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}})})}),[4,p()];case 1:(t=m.sent()).linkerEnabled||console.info("Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414"),n=t.assemblies.map(function(e){return"_framework/_bin/"+e}),m.label=2;case 2:return m.trys.push([2,4,,5]),[4,e.start(n)];case 3:return m.sent(),[3,5];case 4:throw s=m.sent(),new Error("Failed to start platform. Reason: "+s);case 5:return e.callEntryPoint(t.entryAssembly),[2]}})})}function p(){return r(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,fetch("_framework/blazor.boot.json",{method:"Get",credentials:"include"})];case 1:return[2,e.sent().json()]}})})}window.Blazor.start=f,s.shouldAutoStart()&&f()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o,a,i,l,u,s,c,d=n(35),f=n(47),p=n(32),m={},h={},v={},y="appBinDir",g=Math.pow(2,32),b=Math.pow(2,21)-1;function w(e,t,n){var a="["+e+"]"+t+"."+n,i=h[a];if(!i){if(!(i=o(function(e){var t=m[e];if(!t){if(!(t=r(e)))throw new Error('Could not find assembly "'+e+'"');m[e]=t}return t}(e),t,n)))throw new Error('Could not find type "'+n+'" in namespace "'+t+'" in assembly "'+e+'"');h[a]=i}return i}function E(e,t,n,r){var o="["+e+"]"+t+"."+n+"::"+r,i=v[o];if(!i){if(!(i=a(w(e,t,n),r,-1)))throw new Error('Could not find method "'+r+'" on type "'+t+"."+n+'"');v[o]=i}return i}t.monoPlatform={start:function(e){return new Promise(function(n,m){var h,v;f.attachDebuggerHotkey(e),window.Browser={init:function(){}},h=function(){window.Module=function(e,n,m){var h={},v=["DEBUGGING ENABLED"];return h.print=function(e){return v.indexOf(e)<0&&console.log("WASM: "+e)},h.printErr=function(e){console.error("WASM: "+e),p.showErrorNotification()},h.preRun=[],h.postRun=[],h.preloadPlugins=[],h.locateFile=function(e){switch(e){case"mono.wasm":return"_framework/wasm/mono.wasm";default:return e}},h.preRun.push(function(){var t=Module.cwrap("mono_wasm_add_assembly",null,["string","number","number"]);r=Module.cwrap("mono_wasm_assembly_load","number",["string"]),o=Module.cwrap("mono_wasm_assembly_find_class","number",["number","string","string"]),a=Module.cwrap("mono_wasm_assembly_find_method","number",["number","string","number"]),i=Module.cwrap("mono_wasm_invoke_method","number",["number","number","number"]),l=Module.mono_call_assembly_entry_point,s=Module.cwrap("mono_wasm_string_get_utf8","number",["number"]),c=Module.cwrap("mono_wasm_string_from_js","number",["string"]),u=Module.cwrap("mono_wasm_obj_array_new","number",["number"]),MONO.loaded_files=[],e.forEach(function(e){var n=d.getFileNameFromUrl(e),r="blazor:"+n;addRunDependency(r),function(e){return new Promise(function(t,n){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){if(200==r.status||0==r.status&&r.response){var e=new Uint8Array(r.response);t(e)}else n(r)},r.onerror=n,r.send(void 0)})}(e).then(function(o){var a,i=Module._malloc(o.length);new Uint8Array(Module.HEAPU8.buffer,i,o.length).set(o),t(n,i,o.length),MONO.loaded_files.push((a=e,_.href=a,_.href)),removeRunDependency(r)},function(e){e instanceof XMLHttpRequest&&404===e.status&&n.match(/\.pdb$/)||m(e),removeRunDependency(r)})})}),h.postRun.push(function(){var e,r,o;MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE","true"),Module.cwrap("mono_wasm_load_runtime",null,["string","number"])(y,f.hasDebuggingEnabled()?1:0),MONO.mono_wasm_runtime_is_ready=!0,e=E("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","InvokeDotNet"),r=E("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","BeginInvokeDotNet"),o=E("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","EndInvokeJS"),DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,n,o,a,i){if(!a&&!n)throw new Error("Either assemblyName or dotNetObjectId must have a non null value.");var l=a?a.toString():n;t.monoPlatform.callMethod(r,null,[e?t.monoPlatform.toDotNetString(e.toString()):null,t.monoPlatform.toDotNetString(l),t.monoPlatform.toDotNetString(o),t.monoPlatform.toDotNetString(i)])},endInvokeJSFromDotNet:function(e,n,r){t.monoPlatform.callMethod(o,null,[t.monoPlatform.toDotNetString(r)])},invokeDotNetFromJS:function(n,r,o,a){var i=t.monoPlatform.callMethod(e,null,[n?t.monoPlatform.toDotNetString(n):null,t.monoPlatform.toDotNetString(r),o?t.monoPlatform.toDotNetString(o.toString()):null,t.monoPlatform.toDotNetString(a)]);return i?t.monoPlatform.toJavaScriptString(i):null}}),n()}),h}(e,n,m),function(){if("undefined"==typeof WebAssembly||!WebAssembly.validate)throw new Error("This browser does not support WebAssembly.");var e=document.createElement("script");e.src="_framework/wasm/mono.js",e.defer=!0,document.body.appendChild(e)}()},v=document.createElement("script"),window.__wasmmodulecallback__=h,v.type="text/javascript",v.text="var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;",document.body.appendChild(v)})},findMethod:E,callEntryPoint:function(e){var t=u(0);return l(e,[t])},callMethod:function(e,n,r){if(r.length>4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u<r.length;++u)Module.setValue(a+4*u,r[u],"i32");Module.setValue(l,0,"i32");var s=i(e,n,a,l);if(0!==Module.getValue(l,"i32"))throw new Error(t.monoPlatform.toJavaScriptString(s));return s}finally{Module.stackRestore(o)}},toJavaScriptString:function(e){var t=s(e),n=Module.UTF8ToString(t);return Module._free(t),n},toDotNetString:function(e){return c(e)},toUint8Array:function(e){var t=I(e),n=Module.getValue(t,"i32");return new Uint8Array(Module.HEAPU8.buffer,t+4,n)},getArrayLength:function(e){return Module.getValue(I(e),"i32")},getArrayEntryPtr:function(e,t,n){return I(e)+4+t*n},getObjectFieldsBaseAddress:function(e){return e+8},readInt16Field:function(e,t){return Module.getValue(e+(t||0),"i16")},readInt32Field:function(e,t){return Module.getValue(e+(t||0),"i32")},readUint64Field:function(e,t){var n=e+(t||0)>>2,r=Module.HEAPU32[n+1];if(r>b)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*g+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var _=document.createElement("a");function I(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function u(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=u,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");u(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),u=r.values(o),l=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f<l;f++){var p=t.updatedComponentsEntry(u,f),m=d.componentId(p),h=d.edits(p);n.updateComponent(t,m,h,c)}var v=t.disposedComponentIds(),y=r.values(v),g=r.count(v);for(f=0;f<g;f++)m=t.disposedComponentIdsEntry(y,f),n.disposeComponent(m);var b=t.disposedEventHandlerIds(),w=r.values(b),E=r.count(b);for(f=0;f<E;f++){var _=t.disposedEventHandlerIdsEntry(w,f);n.disposeEventHandler(_)}i&&(i=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){i=!0}},,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17);var a,i=n(5),u=!1,l=!1,s=null;function c(e,t){var n=p(e);if(!t&&m(n))d(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function d(e,t){i.resetScrollAfterNextBatch(),history.pushState(null,"",e),f(t)}function f(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return s?[4,s(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(a=a||document.createElement("a")).href=e,a.href}function m(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(s=e,l)return;l=!0,window.addEventListener("popstate",function(){return f(!1)})},enableNavigationInterception:function(){u=!0},navigateTo:c,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(u&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));m(r)&&(e.preventDefault(),d(r,!0))}}})},t.navigateTo=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),a=p("_blazorLogicalEnd");function i(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function u(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(l(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n<i.length){var u=i[n];u.parentNode.insertBefore(e,u),i.splice(n,0,a)}else f(e,t),i.push(a);a[o]=t,r in a||(a[r]=[])}function l(e){return e[o]||null}function s(e){return e[r]}function c(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function d(e){var t=s(l(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function f(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=d(t);n?n.parentNode.insertBefore(e,n):f(e,l(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=i(n,!0),u=s(r);return Array.from(n.childNodes).forEach(function(e){return u.push(e)}),e[o]=r,t&&(e[a]=t,i(t,!0)),i(e,!0)},t.toLogicalElement=i,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return u(n,e,t),n},t.insertLogicalChild=u,t.removeLogicalChild=function e(t,n){var r=s(t).splice(n,1)[0];if(r instanceof Comment)for(var o=s(r);o.length>0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=l,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=l(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function u(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function l(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,u=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var l=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,l)}catch(e){c(i,!1,e)}return u}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return u(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return l(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,d(t));return null==n?null:JSON.stringify(n,h)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,d(n)))});e&&r.then(function(t){return s().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],h))},function(t){return s().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,f(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);c(parseInt(e),t,r)}};var m=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return u(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return l(null,e,this._id,t)},e.prototype.dispose=function(){l(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function h(e,t){return t instanceof m?t.serializeAsArg():t}i(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new m(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(12),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),a=n(13),i=n(31),u=n(19),l=n(12),s=document.createElement("template"),c=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},f={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var a={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};u.dispatchEvent(a,r.data)}(e,t.browserRendererId,n,r,o)}),l.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),f[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var i=f[t];if(i){var u=a.getLogicalSiblingEnd(i);delete f[t],u?function(e,t){var n=a.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=a.getLogicalChildrenArray(n),o=r.indexOf(e)+1,i=r.indexOf(t),u=o;u<=i;u++)a.removeLogicalChild(n,o);e.textContent="!"}(i,u):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(i)}var l=a.getClosestDomElement(o).ownerDocument,s=l&&l.activeElement;this.applyEdits(e,t,o,0,n,r),s instanceof HTMLElement&&l&&l.activeElement!==s&&s.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,i,u){for(var l,s=0,c=o,d=e.arrayBuilderSegmentReader,f=e.editReader,p=e.frameReader,m=d.values(i),h=d.offset(i),v=h+d.count(i),y=h;y<v;y++){var g=e.diffReader.editsEntry(m,y),b=f.editType(g);switch(b){case r.EditType.prependFrame:var w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);this.insertFrame(e,t,n,c+_,u,E,w);break;case r.EditType.removeFrame:_=f.siblingIndex(g);a.removeLogicalChild(n,c+_);break;case r.EditType.setAttribute:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,I,E);break;case r.EditType.removeAttribute:var I;_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var C=f.removedAttributeName(g);this.tryApplySpecialProperty(e,I,C,null)||I.removeAttribute(C);break;case r.EditType.updateText:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);var S=a.getLogicalChild(n,c+_);if(!(S instanceof Text))throw new Error("Cannot set text content on non-text child");S.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);a.removeLogicalChild(n,c+_),this.insertMarkup(e,n,c+_,E);break;case r.EditType.stepIn:_=f.siblingIndex(g);n=a.getLogicalChild(n,c+_),s++,c=0;break;case r.EditType.stepOut:n=a.getLogicalParent(n),c=0===--s?o:0;break;case r.EditType.permutationListEntry:(l=l||[]).push({fromSiblingIndex:c+f.siblingIndex(g),toSiblingIndex:c+f.moveToSiblingIndex(g)});break;case r.EditType.permutationListEnd:a.permuteLogicalChildren(n,l),l=void 0;break;default:throw new Error("Unknown edit type: "+b)}}},e.prototype.insertFrame=function(e,t,n,o,a,u,l){var s=e.frameReader,c=s.frameType(u);switch(c){case r.FrameType.element:return this.insertElement(e,t,n,o,a,u,l),1;case r.FrameType.text:return this.insertText(e,n,o,u),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,u),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,a,l+1,l+s.subtreeLength(u));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return i.applyCaptureIdToElement(n,s.elementReferenceCaptureId(u)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,u),1;default:throw new Error("Unknown frame type: "+c)}},e.prototype.insertElement=function(e,t,n,o,i,u,l){var s=e.frameReader,c=s.elementName(u),d="svg"===c||a.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",c):document.createElement(c),f=a.toLogicalElement(d);a.insertLogicalChild(d,n,o);for(var p=l+s.subtreeLength(u),m=l+1;m<p;m++){var h=e.referenceFramesEntry(i,m);if(s.frameType(h)!==r.FrameType.attribute){this.insertFrameRange(e,t,f,0,i,m,p);break}this.applyAttribute(e,t,d,h)}if(d instanceof HTMLSelectElement&&"_blazorSelectValue"in d){var v=d._blazorSelectValue;d.value=v,delete d._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=a.createAndInsertLogicalContainer(t,n),i=e.frameReader.componentId(r);this.attachComponentToElement(i,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),i=document.createTextNode(o);a.insertLogicalChild(i,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,i=a.createAndInsertLogicalContainer(t,n),u=e.frameReader.markupContent(r),l=(o=u,a.isSvgElement(t)?(c.innerHTML=o||" ",c):(s.innerHTML=o||" ",s.content)),d=0;l.firstChild;)a.insertLogicalChild(l.firstChild,i,d++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,a=o.attributeName(r),i=o.attributeEventHandlerId(r);if(i){var u=h(a);this.eventDelegator.setListener(n,u,i,t)}else this.tryApplySpecialProperty(e,n,a,r)||n.setAttribute(a,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var a=h(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,a,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");a=h(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,a,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var a=n?r.attributeValue(n):null;return t.value=a,"SELECT"===t.tagName&&(t._blazorSelectValue=a),!0;case"OPTION":(a=n?r.attributeValue(n):null)?t.setAttribute("value",a):t.removeAttribute("value");var i=this.findClosestAncestorSelectElement(t);return i&&"_blazorSelectValue"in i&&i._blazorSelectValue===a&&(this.tryApplyValueProperty(e,i,n),delete i._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,a,i){for(var u=r,l=a;l<i;l++){var s=e.referenceFramesEntry(o,l);r+=this.insertFrame(e,t,n,r,o,s,l),l+=m(e,s)}return r-u},e}();function m(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function h(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),a=c(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),i=c(["click","dblclick","mousedown","mousemove","mouseup"]),u=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new l(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{var i={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(i),o.setHandler(t,i)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,u=e.target,l=null,s=a.hasOwnProperty(e.type),c=!1;u;){var d=this.getEventHandlerInfosForElement(u,!1);if(d){var f=d.getHandler(e.type);if(f&&(t=u,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&i.hasOwnProperty(n)&&t.disabled))){l||(l=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(f.renderingComponentId,e);this.onEvent(e,f.eventHandlerId,l,p)}d.stopPropagation(e.type)&&(c=!0),d.preventDefault(e.type)&&e.preventDefault()}u=s||c?null:u.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new s:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=u;var l=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=a.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),s=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function c(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==i.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var u=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:u});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},a(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",a(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},a(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},a(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function a(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var i=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0});var a=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),a||(a=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,function(e,t,n){"use strict";function r(e){var t=e.substring(e.lastIndexOf("/")+1),n=t.indexOf("?");return n<0?t:t.substring(0,n)}Object.defineProperty(t,"__esModule",{value:!0}),t.getFileNameFromUrl=r,t.getAssemblyNameFromUrl=function(e){return r(e).replace(/\.dll$/,"")}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17),n(24);var a=n(18),i=n(46),u=n(5),l=n(48),s=n(33),c=n(19),d=!1;function f(e){return r(this,void 0,void 0,function(){var e,t,n,s,f=this;return o(this,function(m){switch(m.label){case 0:if(d)throw new Error("Blazor has already started.");return d=!0,c.setEventDispatcher(function(e,t){return DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","DispatchEvent",e,JSON.stringify(t))}),e=a.setPlatform(i.monoPlatform),window.Blazor.platform=e,window.Blazor._internal.renderBatch=function(e,t){u.renderBatch(e,new l.SharedMemoryRenderBatch(t))},window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return r(f,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}})})}),[4,p()];case 1:(t=m.sent()).linkerEnabled||console.info("Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414"),n=t.assemblies.map(function(e){return"_framework/_bin/"+e}),m.label=2;case 2:return m.trys.push([2,4,,5]),[4,e.start(n)];case 3:return m.sent(),[3,5];case 4:throw s=m.sent(),new Error("Failed to start platform. Reason: "+s);case 5:return e.callEntryPoint(t.entryAssembly),[2]}})})}function p(){return r(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,fetch("_framework/blazor.boot.json",{method:"Get",credentials:"include"})];case 1:return[2,e.sent().json()]}})})}window.Blazor.start=f,s.shouldAutoStart()&&f().catch(function(e){Module.printErr(e)})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o=n(35),a=n(47),i=n(32),u="appBinDir",l=Math.pow(2,32),s=Math.pow(2,21)-1;t.monoPlatform={start:function(e){return new Promise(function(t,n){var l,s;a.attachDebuggerHotkey(e),window.Browser={init:function(){}},l=function(){window.Module=function(e,t,n){var l={},s=["DEBUGGING ENABLED"];return l.print=function(e){return s.indexOf(e)<0&&console.log("WASM: "+e)},l.printErr=function(e){console.error("WASM: "+e),i.showErrorNotification()},l.preRun=[],l.postRun=[],l.preloadPlugins=[],l.locateFile=function(e){switch(e){case"mono.wasm":return"_framework/wasm/mono.wasm";default:return e}},l.preRun.push(function(){var t=Module.cwrap("mono_wasm_add_assembly",null,["string","number","number"]);r=Module.cwrap("mono_wasm_string_get_utf8","number",["number"]),MONO.loaded_files=[],e.forEach(function(e){var r=o.getFileNameFromUrl(e),a="blazor:"+r;addRunDependency(a),function(e){return new Promise(function(t,n){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){if(200==r.status||0==r.status&&r.response){var e=new Uint8Array(r.response);t(e)}else n(r)},r.onerror=n,r.send(void 0)})}(e).then(function(n){var o,i=Module._malloc(n.length);new Uint8Array(Module.HEAPU8.buffer,i,n.length).set(n),t(r,i,n.length),MONO.loaded_files.push((o=e,c.href=o,c.href)),removeRunDependency(a)},function(e){e instanceof XMLHttpRequest&&404===e.status&&r.match(/\.pdb$/)||n(e),removeRunDependency(a)})})}),l.postRun.push(function(){var e,n,r;MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE","true"),Module.cwrap("mono_wasm_load_runtime",null,["string","number"])(u,a.hasDebuggingEnabled()?1:0),MONO.mono_wasm_runtime_is_ready=!0,e=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","InvokeDotNet"),n=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","BeginInvokeDotNet"),r=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","EndInvokeJS"),DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,t,r,o,a){if(!o&&!t)throw new Error("Either assemblyName or dotNetObjectId must have a non null value.");var i=o?o.toString():t;n(e?e.toString():null,i,r,a)},endInvokeJSFromDotNet:function(e,t,n){r(n)},invokeDotNetFromJS:function(t,n,r,o){return e(t||null,n,r?r.toString():null,o)}}),t()}),l}(e,t,n),function(){if("undefined"==typeof WebAssembly||!WebAssembly.validate)throw new Error("This browser does not support WebAssembly.");var e=document.createElement("script");e.src="_framework/wasm/mono.js",e.defer=!0,document.body.appendChild(e)}()},s=document.createElement("script"),window.__wasmmodulecallback__=l,s.type="text/javascript",s.text="var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;",document.body.appendChild(s)})},callEntryPoint:function(e){f("Microsoft.AspNetCore.Blazor","Microsoft.AspNetCore.Blazor.Hosting.EntrypointInvoker","InvokeEntrypoint")(e,null)},toJavaScriptString:function(e){var t=r(e),n=Module.UTF8ToString(t);return Module._free(t),n},toUint8Array:function(e){var t=d(e),n=Module.getValue(t,"i32");return new Uint8Array(Module.HEAPU8.buffer,t+4,n)},getArrayLength:function(e){return Module.getValue(d(e),"i32")},getArrayEntryPtr:function(e,t,n){return d(e)+4+t*n},getObjectFieldsBaseAddress:function(e){return e+8},readInt16Field:function(e,t){return Module.getValue(e+(t||0),"i16")},readInt32Field:function(e,t){return Module.getValue(e+(t||0),"i32")},readUint64Field:function(e,t){var n=e+(t||0)>>2,r=Module.HEAPU32[n+1];if(r>s)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*l+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var c=document.createElement("a");function d(e){return e+12}function f(e,t,n){var r="["+e+"] "+t+":"+n;return Module.mono_bind_static_method(r)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=u,this.editReader=l,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,u.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},u={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,l.structLength)}},l={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 527dcd5ab8ae..cf637d8444bf 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -1,19 +1,9 @@ -import { MethodHandle, System_Object, System_String, System_Array, Pointer, Platform } from '../Platform'; +import { System_Object, System_String, System_Array, Pointer, Platform } from '../Platform'; import { getFileNameFromUrl } from '../Url'; import { attachDebuggerHotkey, hasDebuggingEnabled } from './MonoDebugger'; import { showErrorNotification } from '../../BootErrors'; -const assemblyHandleCache: { [assemblyName: string]: number } = {}; -const typeHandleCache: { [fullyQualifiedTypeName: string]: number } = {}; -const methodHandleCache: { [fullyQualifiedMethodName: string]: MethodHandle } = {}; - -let assembly_load: (assemblyName: string) => number; -let find_class: (assemblyHandle: number, namespace: string, className: string) => number; -let find_method: (typeHandle: number, methodName: string, unknownArg: number) => MethodHandle; -let invoke_method: (method: MethodHandle, target: System_Object, argsArrayPtr: number, exceptionFlagIntPtr: number) => System_Object; -let mono_string_array_new: (length: number) => System_Array<System_String>; let mono_string_get_utf8: (managedString: System_String) => Mono.Utf8Ptr; -let mono_string: (jsString: string) => System_String; const appBinDirName = 'appBinDir'; const uint64HighOrderShift = Math.pow(2, 32); const maxSafeNumberHighPart = Math.pow(2, 21) - 1; // The high-order int32 from Number.MAX_SAFE_INTEGER @@ -38,8 +28,6 @@ export const monoPlatform: Platform = { }); }, - findMethod: findMethod, - callEntryPoint: function callEntryPoint(assemblyName: string) { // Instead of using Module.mono_call_assembly_entry_point, we have our own logic for invoking // the entrypoint which adds support for async main. @@ -47,40 +35,9 @@ export const monoPlatform: Platform = { // In the future, we might want Blazor.start to return a Promise<Promise<value>>, where the // outer promise reflects the startup process, and the inner one reflects the possibly-async // .NET entrypoint method. - const invokeEntrypoint = findMethod('Microsoft.AspNetCore.Blazor', 'Microsoft.AspNetCore.Blazor.Hosting', 'EntrypointInvoker', 'InvokeEntrypoint'); - this.callMethod(invokeEntrypoint, null, [ - this.toDotNetString(assemblyName), - mono_string_array_new(0) // In the future, we may have a way of supplying arg strings. For now, we always supply an empty string[]. - ]); - }, - - callMethod: function callMethod(method: MethodHandle, target: System_Object, args: System_Object[]): System_Object { - if (args.length > 4) { - // Hopefully this restriction can be eased soon, but for now make it clear what's going on - throw new Error(`Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass ${args.length}.`); - } - - const stack = Module.stackSave(); - - try { - const argsBuffer = Module.stackAlloc(args.length); - const exceptionFlagManagedInt = Module.stackAlloc(4); - for (let i = 0; i < args.length; ++i) { - Module.setValue(argsBuffer + i * 4, args[i], 'i32'); - } - Module.setValue(exceptionFlagManagedInt, 0, 'i32'); - - const res = invoke_method(method, target, argsBuffer, exceptionFlagManagedInt); - - if (Module.getValue(exceptionFlagManagedInt, 'i32') !== 0) { - // If the exception flag is set, the returned value is exception.ToString() - throw new Error(monoPlatform.toJavaScriptString(<System_String>res)); - } - - return res; - } finally { - Module.stackRestore(stack); - } + const invokeEntrypoint = bindStaticMethod('Microsoft.AspNetCore.Blazor', 'Microsoft.AspNetCore.Blazor.Hosting.EntrypointInvoker', 'InvokeEntrypoint'); + // Note we're passing in null because passing arrays is problematic until https://github.com/mono/mono/issues/18245 is resolved. + invokeEntrypoint(assemblyName, null); }, toJavaScriptString: function toJavaScriptString(managedString: System_String) { @@ -94,10 +51,6 @@ export const monoPlatform: Platform = { return res; }, - toDotNetString: function toDotNetString(jsString: string): System_String { - return mono_string(jsString); - }, - toUint8Array: function toUint8Array(array: System_Array<any>): Uint8Array { const dataPtr = getArrayDataPointer(array); const length = Module.getValue(dataPtr, 'i32'); @@ -158,44 +111,6 @@ export const monoPlatform: Platform = { }, }; -function findAssembly(assemblyName: string): number { - let assemblyHandle = assemblyHandleCache[assemblyName]; - if (!assemblyHandle) { - assemblyHandle = assembly_load(assemblyName); - if (!assemblyHandle) { - throw new Error(`Could not find assembly "${assemblyName}"`); - } - assemblyHandleCache[assemblyName] = assemblyHandle; - } - return assemblyHandle; -} - -function findType(assemblyName: string, namespace: string, className: string): number { - const fullyQualifiedTypeName = `[${assemblyName}]${namespace}.${className}`; - let typeHandle = typeHandleCache[fullyQualifiedTypeName]; - if (!typeHandle) { - typeHandle = find_class(findAssembly(assemblyName), namespace, className); - if (!typeHandle) { - throw new Error(`Could not find type "${className}" in namespace "${namespace}" in assembly "${assemblyName}"`); - } - typeHandleCache[fullyQualifiedTypeName] = typeHandle; - } - return typeHandle; -} - -function findMethod(assemblyName: string, namespace: string, className: string, methodName: string): MethodHandle { - const fullyQualifiedMethodName = `[${assemblyName}]${namespace}.${className}::${methodName}`; - let methodHandle = methodHandleCache[fullyQualifiedMethodName]; - if (!methodHandle) { - methodHandle = find_method(findType(assemblyName, namespace, className), methodName, -1); - if (!methodHandle) { - throw new Error(`Could not find method "${methodName}" on type "${namespace}.${className}"`); - } - methodHandleCache[fullyQualifiedMethodName] = methodHandle; - } - return methodHandle; -} - function addScriptTagsToDocument() { const browserSupportsNativeWebAssembly = typeof WebAssembly !== 'undefined' && WebAssembly.validate; if (!browserSupportsNativeWebAssembly) { @@ -254,26 +169,8 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () 'number', 'number', ]); - assembly_load = Module.cwrap('mono_wasm_assembly_load', 'number', ['string']); - find_class = Module.cwrap('mono_wasm_assembly_find_class', 'number', [ - 'number', - 'string', - 'string', - ]); - find_method = Module.cwrap('mono_wasm_assembly_find_method', 'number', [ - 'number', - 'string', - 'number', - ]); - invoke_method = Module.cwrap('mono_wasm_invoke_method', 'number', [ - 'number', - 'number', - 'number', - ]); mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']); - mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); - mono_string_array_new = Module.cwrap('mono_wasm_string_array_new', 'number', ['number']); MONO.loaded_files = []; @@ -346,10 +243,16 @@ function getArrayDataPointer<T>(array: System_Array<T>): number { return <number><any>array + 12; // First byte from here is length, then following bytes are entries } +function bindStaticMethod(assembly: string, typeName: string, method: string) : (...args: any[]) => any { + // Fully qualified name looks like this: "[debugger-test] Math:IntAdd" + const fqn = `[${assembly}] ${typeName}:${method}`; + return Module.mono_bind_static_method(fqn); +} + function attachInteropInvoker(): void { - const dotNetDispatcherInvokeMethodHandle = findMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop', 'MonoWebAssemblyJSRuntime', 'InvokeDotNet'); - const dotNetDispatcherBeginInvokeMethodHandle = findMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop', 'MonoWebAssemblyJSRuntime', 'BeginInvokeDotNet'); - const dotNetDispatcherEndInvokeJSMethodHandle = findMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop', 'MonoWebAssemblyJSRuntime', 'EndInvokeJS'); + const dotNetDispatcherInvokeMethodHandle = bindStaticMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime', 'InvokeDotNet'); + const dotNetDispatcherBeginInvokeMethodHandle = bindStaticMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime', 'BeginInvokeDotNet'); + const dotNetDispatcherEndInvokeJSMethodHandle = bindStaticMethod('Mono.WebAssembly.Interop', 'Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime', 'EndInvokeJS'); DotNet.attachDispatcher({ beginInvokeDotNetFromJS: (callId: number, assemblyName: string | null, methodIdentifier: string, dotNetObjectId: any | null, argsJson: string): void => { @@ -362,30 +265,25 @@ function attachInteropInvoker(): void { ? dotNetObjectId.toString() : assemblyName; - monoPlatform.callMethod(dotNetDispatcherBeginInvokeMethodHandle, null, [ - callId ? monoPlatform.toDotNetString(callId.toString()) : null, - monoPlatform.toDotNetString(assemblyNameOrDotNetObjectId), - monoPlatform.toDotNetString(methodIdentifier), - monoPlatform.toDotNetString(argsJson), - ]); + dotNetDispatcherBeginInvokeMethodHandle( + callId ? callId.toString() : null, + assemblyNameOrDotNetObjectId, + methodIdentifier, + argsJson, + ); }, endInvokeJSFromDotNet: (asyncHandle, succeeded, serializedArgs): void => { - monoPlatform.callMethod( - dotNetDispatcherEndInvokeJSMethodHandle, - null, - [monoPlatform.toDotNetString(serializedArgs)] + dotNetDispatcherEndInvokeJSMethodHandle( + serializedArgs ); }, invokeDotNetFromJS: (assemblyName, methodIdentifier, dotNetObjectId, argsJson) => { - const resultJsonStringPtr = monoPlatform.callMethod(dotNetDispatcherInvokeMethodHandle, null, [ - assemblyName ? monoPlatform.toDotNetString(assemblyName) : null, - monoPlatform.toDotNetString(methodIdentifier), - dotNetObjectId ? monoPlatform.toDotNetString(dotNetObjectId.toString()) : null, - monoPlatform.toDotNetString(argsJson), - ]) as System_String; - return resultJsonStringPtr - ? monoPlatform.toJavaScriptString(resultJsonStringPtr) - : null; + return dotNetDispatcherInvokeMethodHandle( + assemblyName ? assemblyName : null, + methodIdentifier, + dotNetObjectId ? dotNetObjectId.toString() : null, + argsJson, + ) as string; }, }); } diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoTypes.d.ts b/src/Components/Web.JS/src/Platform/Mono/MonoTypes.d.ts index 0fc613915b42..7d2f5c23bf03 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoTypes.d.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoTypes.d.ts @@ -10,7 +10,7 @@ declare namespace Module { function FS_createPath(parent, path, canRead, canWrite); function FS_createDataFile(parent, name, data, canRead, canWrite, canOwn); - function mono_call_assembly_entry_point(assemblyName: string, args: any[]): any; + function mono_bind_static_method(fqn: string): BoundStaticMethod; } // Emscripten declares these globals @@ -28,3 +28,7 @@ declare namespace MONO { var mono_wasm_runtime_is_ready: boolean; function mono_wasm_setenv (name: string, value: string): void; } + +// mono_bind_static_method allows arbitrary JS data types to be sent over the wire. However we are +// artifically limiting it to a subset of types that we actually use. +declare type BoundStaticMethod = (...args: (string | number | null)[]) => (string | number | null); diff --git a/src/Components/Web.JS/src/Platform/Platform.ts b/src/Components/Web.JS/src/Platform/Platform.ts index 29eb04609e7a..8d5daf454a3f 100644 --- a/src/Components/Web.JS/src/Platform/Platform.ts +++ b/src/Components/Web.JS/src/Platform/Platform.ts @@ -2,12 +2,8 @@ export interface Platform { start(loadAssemblyUrls: string[]): Promise<void>; callEntryPoint(assemblyName: string): void; - findMethod(assemblyName: string, namespace: string, className: string, methodName: string): MethodHandle; - callMethod(method: MethodHandle, target: System_Object | null, args: (System_Object | null)[]): System_Object; toJavaScriptString(dotNetString: System_String): string; - toDotNetString(javaScriptString: string): System_String; - toUint8Array(array: System_Array<any>): Uint8Array; getArrayLength(array: System_Array<any>): number; From 1c3ae1549e3f3137ccfafc0de4753dc358b4e441 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 3 Dec 2019 14:41:28 -0800 Subject: [PATCH 037/322] Add publish test for BlazorStandalone --- .config/dotnet-tools.json | 12 +++++++ .../test/BlazorWasmTemplateTest.cs | 22 +++++++++--- .../test/Helpers/AspNetProcess.cs | 9 +++-- src/ProjectTemplates/test/Helpers/Project.cs | 34 +++++++++++++------ .../test/ProjectTemplates.Tests.csproj | 4 +++ 5 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 .config/dotnet-tools.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 000000000000..be95a01fc500 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-serve": { + "version": "1.5.0", + "commands": [ + "dotnet-serve" + ] + } + } +} \ No newline at end of file diff --git a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs index 579d5b11bf13..41cb82ac21ec 100644 --- a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs @@ -6,7 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.E2ETesting; -using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.CommandLineUtils; using OpenQA.Selenium; using Templates.Test.Helpers; using Xunit; @@ -28,11 +28,11 @@ public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixtu public async Task BlazorWasmStandaloneTemplate_Works() { var project = await ProjectFactory.GetOrCreateProject("blazorstandalone", Output); + project.TargetFramework = "netstandard2.1"; var createResult = await project.RunDotNetNewAsync("blazorwasm"); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); - // We can't run a published standalone app, but let's just make sure it publishes fine var publishResult = await project.RunDotNetPublishAsync(); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult)); @@ -40,6 +40,18 @@ public async Task BlazorWasmStandaloneTemplate_Works() Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult)); await BuildAndRunTest(project.ProjectName, project); + + var publishDir = Path.Combine(project.TemplatePublishDir, project.ProjectName, "dist"); + AspNetProcess.EnsureDevelopmentCertificates(); + + Output.WriteLine("Running dotnet serve on published output..."); + using var serveProcess = ProcessEx.Run(Output, publishDir, DotNetMuxer.MuxerPathOrDefault(), "serve -S"); + + // Todo: Use dynamic port assignment: https://github.com/natemcmaster/dotnet-serve/pull/40/files + var listeningUri = "https://localhost:8080"; + Output.WriteLine($"Opening browser at {listeningUri}..."); + Browser.Navigate().GoToUrl(listeningUri); + TestBasicNavigation(project.ProjectName); } [Fact] @@ -70,7 +82,7 @@ public async Task BlazorWasmHostedTemplate_Works() if (BrowserFixture.IsHostAutomationSupported()) { aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(project.ProjectName, serverProject); + TestBasicNavigation(project.ProjectName); } else { @@ -90,7 +102,7 @@ protected async Task BuildAndRunTest(string appName, Project project) if (BrowserFixture.IsHostAutomationSupported()) { aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(appName, project); + TestBasicNavigation(appName); } else { @@ -98,7 +110,7 @@ protected async Task BuildAndRunTest(string appName, Project project) } } - private void TestBasicNavigation(string appName, Project project) + private void TestBasicNavigation(string appName) { // Give components.server enough time to load so that it can replace // the prerendered content before we start making assertions. diff --git a/src/ProjectTemplates/test/Helpers/AspNetProcess.cs b/src/ProjectTemplates/test/Helpers/AspNetProcess.cs index c4415bf55f0d..753eb1258a52 100644 --- a/src/ProjectTemplates/test/Helpers/AspNetProcess.cs +++ b/src/ProjectTemplates/test/Helpers/AspNetProcess.cs @@ -51,8 +51,7 @@ public AspNetProcess( Timeout = TimeSpan.FromMinutes(2) }; - var now = DateTimeOffset.Now; - new CertificateManager().EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1)); + EnsureDevelopmentCertificates(); output.WriteLine("Running ASP.NET application..."); @@ -64,6 +63,12 @@ public AspNetProcess( } } + internal static void EnsureDevelopmentCertificates() + { + var now = DateTimeOffset.Now; + new CertificateManager().EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1)); + } + public void VisitInBrowser(IWebDriver driver) { _output.WriteLine($"Opening browser at {ListeningUri}..."); diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs index 8eb59d86f62b..19f1d46b7f95 100644 --- a/src/ProjectTemplates/test/Helpers/Project.cs +++ b/src/ProjectTemplates/test/Helpers/Project.cs @@ -21,13 +21,10 @@ public class Project { private const string _urls = "http://127.0.0.1:0;https://127.0.0.1:0"; - public const string DefaultFramework = "netcoreapp3.1"; - public static bool IsCIEnvironment => typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() .Any(a => a.Key == "ContinuousIntegrationBuild"); - public static string ArtifactsLogDir => typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() - .Single(a => a.Key == "ArtifactsLogDir")?.Value; + public static string ArtifactsLogDir => GetAssemblyMetadata("ArtifactsLogDir"); public SemaphoreSlim DotNetNewLock { get; set; } public SemaphoreSlim NodeLock { get; set; } @@ -35,14 +32,16 @@ public class Project public string ProjectArguments { get; set; } public string ProjectGuid { get; set; } public string TemplateOutputDir { get; set; } - public string TemplateBuildDir => Path.Combine(TemplateOutputDir, "bin", "Debug", DefaultFramework); - public string TemplatePublishDir => Path.Combine(TemplateOutputDir, "bin", "Release", DefaultFramework, "publish"); + public string TargetFramework { get; set; } = GetAssemblyMetadata("Test.DefaultTargetFramework"); + + public string TemplateBuildDir => Path.Combine(TemplateOutputDir, "bin", "Debug", TargetFramework); + public string TemplatePublishDir => Path.Combine(TemplateOutputDir, "bin", "Release", TargetFramework, "publish"); private string TemplateServerDir => Path.Combine(TemplateOutputDir, $"{ProjectName}.Server"); private string TemplateClientDir => Path.Combine(TemplateOutputDir, $"{ProjectName}.Client"); - public string TemplateClientDebugDir => Path.Combine(TemplateClientDir, "bin", "Debug", DefaultFramework); - public string TemplateClientReleaseDir => Path.Combine(TemplateClientDir, "bin", "Release", DefaultFramework, "publish"); - public string TemplateServerReleaseDir => Path.Combine(TemplateServerDir, "bin", "Release", DefaultFramework, "publish"); + public string TemplateClientDebugDir => Path.Combine(TemplateClientDir, "bin", "Debug", TargetFramework); + public string TemplateClientReleaseDir => Path.Combine(TemplateClientDir, "bin", "Release", TargetFramework, "publish"); + public string TemplateServerReleaseDir => Path.Combine(TemplateServerDir, "bin", "Release", TargetFramework, "publish"); public ITestOutputHelper Output { get; set; } public IMessageSink DiagnosticsMessageSink { get; set; } @@ -110,7 +109,7 @@ internal async Task<ProcessEx> RunDotNetNewAsync( } } - internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null) + internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string, string> packageOptions = null, string additionalArgs = null) { Output.WriteLine("Publishing ASP.NET application..."); @@ -132,7 +131,7 @@ internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, } } - internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null) + internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string, string> packageOptions = null, string additionalArgs = null) { Output.WriteLine("Building ASP.NET application..."); @@ -524,5 +523,18 @@ private void CaptureBinLogOnFailure(ProcessEx result) } public override string ToString() => $"{ProjectName}: {TemplateOutputDir}"; + + private static string GetAssemblyMetadata(string key) + { + var attribute = typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() + .FirstOrDefault(a => a.Key == key); + + if (attribute is null) + { + throw new ArgumentException($"AssemblyMetadataAttribute with key {key} was not found."); + } + + return attribute.Value; + } } } diff --git a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj index 492f337109f4..6eb7d6c45454 100644 --- a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj +++ b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj @@ -58,6 +58,10 @@ <_Parameter1>TestPackageRestorePath</_Parameter1> <_Parameter2>$(TestPackageRestorePath)</_Parameter2> </AssemblyAttribute> + <AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute"> + <_Parameter1>Test.DefaultTargetFramework</_Parameter1> + <_Parameter2>$(DefaultNetCoreTargetFramework)</_Parameter2> + </AssemblyAttribute> <AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="'$(ContinuousIntegrationBuild)' == 'true'"> <_Parameter1>ContinuousIntegrationBuild</_Parameter1> <_Parameter2>true</_Parameter2> From baf72c73c53156d19a0c82d104ec0021c245f971 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Fri, 3 Jan 2020 14:34:03 -0800 Subject: [PATCH 038/322] Avoid copying the shared fx in blazor-wasm --- src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj b/src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj index 4c4298a92da7..66680a95a5a6 100644 --- a/src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj +++ b/src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj @@ -167,7 +167,6 @@ This package is an internal implementation of the .NET Core SDK and is not meant _BatchCopyToRedistLayout; _CreateInternalSharedFxArchive; _CreateRedistSharedFxArchive; - _InstallFrameworkIntoLocalDotNet; </CoreBuildDependsOn> <CrossGenDependsOn> ResolveReferences; From 66ecdab542054fc96f102963332e317007d4c437 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Mon, 6 Jan 2020 08:39:56 -0800 Subject: [PATCH 039/322] Ensure $(Configuration) is evaluated prior to using it (#18113) Fixes https://github.com/aspnet/AspNetCore/issues/12779 --- src/Components/Blazor/Build/src/targets/All.props | 6 ------ src/Components/Blazor/Build/src/targets/All.targets | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Components/Blazor/Build/src/targets/All.props b/src/Components/Blazor/Build/src/targets/All.props index 690a29fbab8f..d1d242f4d92f 100644 --- a/src/Components/Blazor/Build/src/targets/All.props +++ b/src/Components/Blazor/Build/src/targets/All.props @@ -4,12 +4,6 @@ <PropertyGroup> <DefaultWebContentItemExcludes>$(DefaultWebContentItemExcludes);wwwroot\**</DefaultWebContentItemExcludes> - <!-- By default, enable auto rebuilds for debug builds. Note that the server will not enable it in production environments regardless. --> - <BlazorRebuildOnFileChange Condition="'$(Configuration)' == 'Debug' AND '$(BlazorRebuildOnFileChange)' == ''">true</BlazorRebuildOnFileChange> - - <!-- By default, enable debugging for debug builds. --> - <BlazorEnableDebugging Condition="'$(Configuration)' == 'Debug' AND '$(BlazorEnableDebugging)' == ''">true</BlazorEnableDebugging> - <!-- 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> </PropertyGroup> diff --git a/src/Components/Blazor/Build/src/targets/All.targets b/src/Components/Blazor/Build/src/targets/All.targets index 6aa60e822760..6c69e85a4011 100644 --- a/src/Components/Blazor/Build/src/targets/All.targets +++ b/src/Components/Blazor/Build/src/targets/All.targets @@ -13,6 +13,9 @@ <!-- 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" /> From d4ada348fba375f3f77ed8ed65d834155ae746f6 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 7 Jan 2020 13:42:25 -0800 Subject: [PATCH 040/322] Use Blazor version for WASM templates (#18174) --- src/Components/Blazor/Blazor.Version.props | 8 ++++++++ src/Components/Blazor/Directory.Build.props | 5 +---- .../Microsoft.AspNetCore.Blazor.Templates.csproj | 8 ++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 src/Components/Blazor/Blazor.Version.props diff --git a/src/Components/Blazor/Blazor.Version.props b/src/Components/Blazor/Blazor.Version.props new file mode 100644 index 000000000000..123a94c1d772 --- /dev/null +++ b/src/Components/Blazor/Blazor.Version.props @@ -0,0 +1,8 @@ +<Project> + <PropertyGroup> + <!-- Override version labels --> + <VersionPrefix>3.2.0</VersionPrefix> + <PreReleaseVersionLabel>preview1</PreReleaseVersionLabel> + <DotNetFinalVersionKind /> + </PropertyGroup> +</Project> \ No newline at end of file diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props index 59beb90ee9d8..8df2e791dd3b 100644 --- a/src/Components/Blazor/Directory.Build.props +++ b/src/Components/Blazor/Directory.Build.props @@ -1,11 +1,8 @@ <Project> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" /> + <Import Project="Blazor.Version.props" /> <PropertyGroup> - <!-- Override version labels --> - <VersionPrefix>3.2.0</VersionPrefix> - <PreReleaseVersionLabel>preview1</PreReleaseVersionLabel> - <DotNetFinalVersionKind /> <!-- This property points to the latest released Microsoft.AspNetCore.App version it needs to be updated to target the latest patch before a preview release. --> <LatestAspNetCoreReferenceVersion>3.1.0</LatestAspNetCoreReferenceVersion> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj index 32c3197d04f7..65457a000d35 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj @@ -1,4 +1,10 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <BlazorProjectsRoot>$(RepoRoot)src\Components\Blazor\</BlazorProjectsRoot> + </PropertyGroup> + + <Import Project="$(BlazorProjectsRoot)Blazor.Version.props" /> + <PropertyGroup> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <IsShippingPackage>true</IsShippingPackage> @@ -18,8 +24,6 @@ MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion); </GeneratedContentProperties> - - <BlazorProjectsRoot>$(RepoRoot)src\Components\Blazor\</BlazorProjectsRoot> </PropertyGroup> <ItemGroup> From a181fd52326e383d33bd36be6e799f31720a823d Mon Sep 17 00:00:00 2001 From: Steve Sanderson <SteveSandersonMS@users.noreply.github.com> Date: Fri, 10 Jan 2020 11:30:55 +0000 Subject: [PATCH 041/322] Link more assemblies (type granularity linking for real this time) (#18165) --- .../Blazor/src/Hosting/WebAssemblyHost.cs | 5 ++ .../GenerateTypeGranularityLinkingConfig.cs | 48 +++++++++++++++++++ .../src/targets/Blazor.MonoRuntime.targets | 15 +++++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/Components/Blazor/Build/src/Tasks/GenerateTypeGranularityLinkingConfig.cs diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs index 3a2ccfbaaee2..b90878fdde36 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs @@ -19,6 +19,11 @@ internal class WebAssemblyHost : IWebAssemblyHost public WebAssemblyHost(IServiceProvider services, IJSRuntime runtime) { + // To ensure JS-invoked methods don't get linked out, have a reference to their enclosing types + GC.KeepAlive(typeof(EntrypointInvoker)); + GC.KeepAlive(typeof(JSInteropMethods)); + GC.KeepAlive(typeof(WebAssemblyEventDispatcher)); + Services = services ?? throw new ArgumentNullException(nameof(services)); _runtime = runtime ?? throw new ArgumentNullException(nameof(runtime)); } diff --git a/src/Components/Blazor/Build/src/Tasks/GenerateTypeGranularityLinkingConfig.cs b/src/Components/Blazor/Build/src/Tasks/GenerateTypeGranularityLinkingConfig.cs new file mode 100644 index 000000000000..8a56b7fc3deb --- /dev/null +++ b/src/Components/Blazor/Build/src/Tasks/GenerateTypeGranularityLinkingConfig.cs @@ -0,0 +1,48 @@ +// 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.Blazor.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"))); + } + } +} diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 0a3ba70a2374..4bdb2f431156 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -160,6 +160,7 @@ </Target> <UsingTask TaskName="BlazorILLink" AssemblyFile="$(BlazorTasksPath)" /> + <UsingTask TaskName="GenerateTypeGranularityLinkingConfig" AssemblyFile="$(BlazorTasksPath)" /> <Target Name="_LinkBlazorApplication" @@ -171,7 +172,10 @@ Outputs="$(_BlazorLinkerOutputCache)"> <ItemGroup> - <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)" IsLinkable="$([System.String]::Copy('%(FileName)').StartsWith('System.'))" /> + <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)" /> + <_BlazorDependencyAssembly IsLinkable="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('System.'))" /> + <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))" /> + <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.'))" /> <_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" /> <_BlazorAssemblyToLink Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" /> @@ -201,6 +205,15 @@ <_DotNetHostFileName Condition=" '$(OS)' == 'Windows_NT' ">dotnet.exe</_DotNetHostFileName> </PropertyGroup> + <PropertyGroup> + <_TypeGranularityLinkingConfig>$(BlazorIntermediateOutputPath)linker.typegranularityconfig.xml</_TypeGranularityLinkingConfig> + </PropertyGroup> + <GenerateTypeGranularityLinkingConfig Assemblies="@(_BlazorAssemblyToLink->WithMetadataValue('TypeGranularity', 'true'))" OutputPath="$(_TypeGranularityLinkingConfig)" /> + <ItemGroup> + <BlazorLinkerDescriptor Include="$(_TypeGranularityLinkingConfig)" /> + <FileWrites Include="$(_TypeGranularityLinkingConfig)" /> + </ItemGroup> + <BlazorILLink ILLinkPath="$(MonoLinkerPath)" AssemblyPaths="@(_BlazorAssemblyToLink)" From cb092258c38dc1d3afac804cce88e54e644883d0 Mon Sep 17 00:00:00 2001 From: Steve Sanderson <SteveSandersonMS@users.noreply.github.com> Date: Thu, 9 Jan 2020 15:46:25 +0000 Subject: [PATCH 042/322] Allow overwriting outputs with older inputs. Fixes #18192 --- .../Blazor/Build/src/targets/Blazor.MonoRuntime.targets | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 4bdb2f431156..24378975a0a8 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -22,8 +22,6 @@ <Target Name="_BlazorCopyFilesToOutputDirectory" DependsOnTargets="PrepareBlazorOutputs" - Inputs="@(BlazorOutputWithTargetPath)" - Outputs="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')" AfterTargets="CopyFilesToOutputDirectory" Condition="'$(OutputType.ToLowerInvariant())'=='exe'"> From 2e2d0625e14d20c4f222affa5bfc20d761c89c54 Mon Sep 17 00:00:00 2001 From: Steve Sanderson <SteveSandersonMS@users.noreply.github.com> Date: Thu, 9 Jan 2020 15:46:51 +0000 Subject: [PATCH 043/322] Write unlinked.output to disk --- .../Blazor/Build/src/targets/Blazor.MonoRuntime.targets | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 24378975a0a8..cdbe7169a06b 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -268,6 +268,8 @@ <Output TaskParameter="Dependencies" ItemName="_BlazorResolvedRuntimeDependencies" /> </ResolveBlazorRuntimeDependencies> + <WriteLinesToFile File="$(_BlazorApplicationAssembliesCacheFile)" Lines="@(_BlazorResolvedRuntimeDependencies)" Overwrite="true" /> + <ItemGroup> <FileWrites Include="$(_BlazorApplicationAssembliesCacheFile)" /> </ItemGroup> From 3fb171e282aa461e054a9969ee023713d92ea04a Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Wed, 8 Jan 2020 13:35:33 -0800 Subject: [PATCH 044/322] Handle satellite assemblies in the Blazor build targets * Pass the same closure of assemblies that is used by the SDK's linker to Blazor's linker and ResolveBlazorRuntimeDependencies task * Quote the mono linker path Fixes https://github.com/dotnet/aspnetcore/issues/17644 Fixes https://github.com/dotnet/aspnetcore/issues/17754 --- .../Blazor/Build/src/Tasks/BlazorILLink.cs | 7 +- .../Build/src/Tasks/GenerateBlazorBootJson.cs | 14 +++- .../src/targets/Blazor.MonoRuntime.targets | 81 ++++++++++++------- .../BuildIntegrationTest.cs | 61 ++++++++++++++ .../PublishIntegrationTest.cs | 29 +++++++ .../Class1.cs | 12 +++ ...classlibrarywithsatelliteassemblies.csproj | 13 +++ .../Build/testassets/standalone/Program.cs | 6 +- 8 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/Class1.cs create mode 100644 src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/classlibrarywithsatelliteassemblies.csproj diff --git a/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs index 5e0a86d384e4..d5dc22cde02c 100644 --- a/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs +++ b/src/Components/Blazor/Build/src/Tasks/BlazorILLink.cs @@ -66,7 +66,12 @@ private string DotNetPath protected override string GenerateFullPathToTool() => DotNetPath; - protected override string GenerateCommandLineCommands() => ILLinkPath; + protected override string GenerateCommandLineCommands() + { + var args = new StringBuilder(); + args.Append(Quote(ILLinkPath)); + return args.ToString(); + } private static string Quote(string path) { diff --git a/src/Components/Blazor/Build/src/Tasks/GenerateBlazorBootJson.cs b/src/Components/Blazor/Build/src/Tasks/GenerateBlazorBootJson.cs index b383d183e4da..1984de0a5798 100644 --- a/src/Components/Blazor/Build/src/Tasks/GenerateBlazorBootJson.cs +++ b/src/Components/Blazor/Build/src/Tasks/GenerateBlazorBootJson.cs @@ -1,6 +1,7 @@ // 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.Reflection; @@ -27,12 +28,23 @@ public class GenerateBlazorBootJson : Task public override bool Execute() { var entryAssemblyName = AssemblyName.GetAssemblyName(AssemblyPath).Name; - var assemblies = References.Select(c => Path.GetFileName(c.ItemSpec)).ToArray(); + var assemblies = References.Select(GetUriPath).OrderBy(c => c, StringComparer.Ordinal).ToArray(); using var fileStream = File.Create(OutputPath); WriteBootJson(fileStream, entryAssemblyName, assemblies, LinkerEnabled); return true; + + static string GetUriPath(ITaskItem item) + { + var outputPath = item.GetMetadata("RelativeOutputPath"); + if (string.IsNullOrEmpty(outputPath)) + { + outputPath = Path.GetFileName(item.ItemSpec); + } + + return outputPath.Replace('\\', '/'); + } } internal static void WriteBootJson(Stream stream, string entryAssemblyName, string[] assemblies, bool linkerEnabled) diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index cdbe7169a06b..915ec80391b3 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -74,7 +74,7 @@ </ItemGroup> </Target> - <Target Name="_ResolveBlazorInputs"> + <Target Name="_ResolveBlazorInputs" DependsOnTargets="ResolveReferences;ResolveRuntimePackAssets"> <PropertyGroup> <!-- /obj/<<configuration>>/<<targetframework>>/blazor --> <BlazorIntermediateOutputPath>$(IntermediateOutputPath)blazor\</BlazorIntermediateOutputPath> @@ -94,8 +94,6 @@ </PropertyGroup> <ItemGroup> - <_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" /> - <_WebAssemblyBCLFolder Include=" $(DotNetWebAssemblyBCLPath); $(DotNetWebAssemblyBCLFacadesPath); @@ -104,6 +102,22 @@ <_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" /> </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 --> + <_BlazorManagedRuntimeAssemby Include="@(RuntimeCopyLocalItems)" /> + + <!-- Assemblies from other references --> + <_BlazorUserRuntimeAssembly Include="@(ReferencePath->WithMetadataValue('CopyLocal', 'true'))" /> + <_BlazorUserRuntimeAssembly Include="@(ReferenceDependencyPaths->WithMetadataValue('CopyLocal', 'true'))" /> + + <_BlazorManagedRuntimeAssemby Include="@(_BlazorUserRuntimeAssembly)" /> + <_BlazorManagedRuntimeAssemby Include="@(IntermediateAssembly)" /> + </ItemGroup> + <MakeDir Directories="$(BlazorIntermediateOutputPath)" /> </Target> @@ -111,6 +125,27 @@ <Error Message="Unrecongnized value for BlazorLinkOnBuild: '$(BlazorLinkOnBuild)'. Valid values are 'true' or 'false'." Condition="'$(BlazorLinkOnBuild)' != 'true' AND '$(BlazorLinkOnBuild)' != 'false'" /> + + <ItemGroup> + <!-- + 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. + --> + <_BlazorCopyLocalPaths Include="@(ReferenceCopyLocalPaths)" /> + <_BlazorCopyLocalPaths Remove="@(_BlazorManagedRuntimeAssemby)" /> + + <BlazorOutputWithTargetPath Include="@(_BlazorCopyLocalPaths)"> + <BlazorRuntimeFile>true</BlazorRuntimeFile> + <TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(_BlazorCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)</TargetOutputPath> + <RelativeOutputPath>%(_BlazorCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)</RelativeOutputPath> + </BlazorOutputWithTargetPath> + + <BlazorOutputWithTargetPath Include="@(_BlazorResolvedAssembly)"> + <BlazorRuntimeFile>true</BlazorRuntimeFile> + <TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath> + <RelativeOutputPath>%(FileName)%(Extension)</RelativeOutputPath> + </BlazorOutputWithTargetPath> + </ItemGroup> </Target> <!-- @@ -128,14 +163,8 @@ <!-- _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="_BlazorLinkedFile"/> + <Output TaskParameter="Lines" ItemName="_BlazorResolvedAssembly"/> </ReadLinesFromFile> - - <ItemGroup> - <BlazorOutputWithTargetPath Include="%(_BlazorLinkedFile.Identity)"> - <TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath> - </BlazorOutputWithTargetPath> - </ItemGroup> </Target> <UsingTask TaskName="BlazorCreateRootDescriptorFile" AssemblyFile="$(BlazorTasksPath)" /> @@ -163,8 +192,7 @@ <Target Name="_LinkBlazorApplication" Inputs="$(ProjectAssetsFile); - @(IntermediateAssembly); - @(_BlazorDependencyInput); + @(_BlazorManagedRuntimeAssemby); @(BlazorLinkerDescriptor); $(MSBuildAllProjects)" Outputs="$(_BlazorLinkerOutputCache)"> @@ -174,12 +202,15 @@ <_BlazorDependencyAssembly IsLinkable="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('System.'))" /> <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))" /> <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.'))" /> + <!-- Any assembly from a package reference that starts with System. file name is allowed to be linked --> + <_BlazorRuntimeCopyLocalItems Include="@(RuntimeCopyLocalItems)" IsLinkable="$([System.String]::Copy('%(FileName)').StartsWith('System.'))" /> <_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" /> - <_BlazorAssemblyToLink Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" /> + <_BlazorAssemblyToLink Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' == 'true'" /> <_BlazorLinkerRoot Include="@(IntermediateAssembly)" /> - <_BlazorLinkerRoot Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' != 'true'" /> + <_BlazorLinkerRoot Include="@(_BlazorUserRuntimeAssembly)" /> + <_BlazorLinkerRoot Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' != 'true'" /> </ItemGroup> <PropertyGroup> @@ -230,29 +261,22 @@ <WriteLinesToFile File="$(_BlazorLinkerOutputCache)" Lines="@(_LinkerResult)" Overwrite="true" /> </Target> - <UsingTask TaskName="ResolveBlazorRuntimeDependencies" AssemblyFile="$(BlazorTasksPath)" /> <Target Name="_ResolveBlazorOutputsWhenNotLinked" DependsOnTargets="_ResolveBlazorRuntimeDependencies" Condition="'$(BlazorLinkOnBuild)' != 'true'"> - <ReadLinesFromFile File="$(_BlazorApplicationAssembliesCacheFile)" Condition="'@(_BlazorResolvedRuntimeDependencies->Count())' == '0'"> - <Output TaskParameter="Lines" ItemName="_BlazorResolvedRuntimeDependencies"/> + <ReadLinesFromFile File="$(_BlazorApplicationAssembliesCacheFile)" Condition="'@(_BlazorResolvedAssembly->Count())' == '0'"> + <Output TaskParameter="Lines" ItemName="_BlazorResolvedAssembly"/> </ReadLinesFromFile> - - <ItemGroup> - <BlazorOutputWithTargetPath Include="@(_BlazorResolvedRuntimeDependencies)"> - <TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath> - </BlazorOutputWithTargetPath> - </ItemGroup> </Target> <Target Name="_ResolveBlazorRuntimeDependencies" Inputs="$(ProjectAssetsFile); @(IntermediateAssembly); - @(_BlazorDependencyInput)" + @(_BlazorManagedRuntimeAssemby)" Outputs="$(_BlazorApplicationAssembliesCacheFile)"> <!-- @@ -262,10 +286,10 @@ --> <ResolveBlazorRuntimeDependencies EntryPoint="@(IntermediateAssembly)" - ApplicationDependencies="@(_BlazorDependencyInput)" + ApplicationDependencies="@(_BlazorManagedRuntimeAssemby)" WebAssemblyBCLAssemblies="@(_WebAssemblyBCLAssembly)"> - <Output TaskParameter="Dependencies" ItemName="_BlazorResolvedRuntimeDependencies" /> + <Output TaskParameter="Dependencies" ItemName="_BlazorResolvedAssembly" /> </ResolveBlazorRuntimeDependencies> <WriteLinesToFile File="$(_BlazorApplicationAssembliesCacheFile)" Lines="@(_BlazorResolvedRuntimeDependencies)" Overwrite="true" /> @@ -282,13 +306,12 @@ Inputs="@(BlazorOutputWithTargetPath)" Outputs="$(BlazorBootJsonIntermediateOutputPath)"> <ItemGroup> - <_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.dll'))" /> - <_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.pdb'))" Condition="'$(BlazorEnableDebugging)' == 'true'" /> + <_BlazorRuntimeFile Include="@(BlazorOutputWithTargetPath->WithMetadataValue('BlazorRuntimeFile', 'true'))" /> </ItemGroup> <GenerateBlazorBootJson AssemblyPath="@(IntermediateAssembly)" - References="@(_AppReferences)" + References="@(_BlazorRuntimeFile)" LinkerEnabled="$(BlazorLinkOnBuild)" OutputPath="$(BlazorBootJsonIntermediateOutputPath)" /> diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs index 1cc39f0d6ec7..027fe5999068 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs @@ -70,5 +70,66 @@ public async Task Build_WithLinkOnBuildDisabled_Works() Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. } + + [Fact] + 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 result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/restore"); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "classlibrarywithsatelliteassemblies.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output. + + var bootJsonPath = Path.Combine(buildOutputDirectory, "dist", "_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_WithBlazorLinkOnBuildFalse_SatelliteAssembliesAreCopiedToBuildOutput() + { + // Arrange + using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" }); + project.AddProjectFileContent( +@" +<PropertyGroup> + <BlazorLinkOnBuild>false</BlazorLinkOnBuild> + <DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants> +</PropertyGroup> +<ItemGroup> + <ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" /> +</ItemGroup>"); + + var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/restore"); + + Assert.BuildPassed(result); + + var buildOutputDirectory = project.BuildOutputDirectory; + + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "classlibrarywithsatelliteassemblies.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output. + + var bootJsonPath = Path.Combine(buildOutputDirectory, "dist", "_framework", "blazor.boot.json"); + Assert.FileContains(result, bootJsonPath, "\"Microsoft.CodeAnalysis.CSharp.dll\""); + Assert.FileContains(result, bootJsonPath, "\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\""); + } } } diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs index 6995ffde4d1e..f1f554d3b9dc 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -112,6 +112,35 @@ public async Task Publish_WithLinkOnBuildDisabled_Works() Assert.FileExists(result, publishDirectory, "web.config"); } + [Fact] + public async Task Publish_SatelliteAssemblies_AreCopiedToBuildOutput() + { + // 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 result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/restore"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath)); + + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output. + + var bootJsonPath = Path.Combine(blazorPublishDirectory, "dist", "_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 Publish_HostedApp_Works() { diff --git a/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/Class1.cs b/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/Class1.cs new file mode 100644 index 000000000000..944699cdb327 --- /dev/null +++ b/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/Class1.cs @@ -0,0 +1,12 @@ +using System; + +namespace classlibrarywithsatelliteassemblies +{ + public class Class1 + { + public static void Test() + { + GC.KeepAlive(typeof(Microsoft.CodeAnalysis.CSharp.CSharpCompilation)); + } + } +} \ No newline at end of file diff --git a/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/classlibrarywithsatelliteassemblies.csproj b/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/classlibrarywithsatelliteassemblies.csproj new file mode 100644 index 000000000000..7081842748da --- /dev/null +++ b/src/Components/Blazor/Build/testassets/classlibrarywithsatelliteassemblies/classlibrarywithsatelliteassemblies.csproj @@ -0,0 +1,13 @@ +<Project Sdk="Microsoft.NET.Sdk.Razor"> + + <PropertyGroup> + <TargetFramework>netstandard2.1</TargetFramework> + <RazorLangVersion>3.0</RazorLangVersion> + </PropertyGroup> + + <ItemGroup> + <!-- The compiler package contains quite a few satellite assemblies --> + <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" /> + </ItemGroup> + +</Project> diff --git a/src/Components/Blazor/Build/testassets/standalone/Program.cs b/src/Components/Blazor/Build/testassets/standalone/Program.cs index 16bfae7e439c..3e46e6331662 100644 --- a/src/Components/Blazor/Build/testassets/standalone/Program.cs +++ b/src/Components/Blazor/Build/testassets/standalone/Program.cs @@ -1,10 +1,14 @@ - +using System; + namespace standalone { public class Program { public static void Main(string[] args) { +#if REFERENCE_classlibrarywithsatelliteassemblies + GC.KeepAlive(typeof(classlibrarywithsatelliteassemblies.Class1)); +#endif } } } From 80a67874c678753e2ba1ee2d19ddb1158da2599e Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Fri, 10 Jan 2020 10:43:25 -0800 Subject: [PATCH 045/322] Resolve merge conflicts --- .../src/targets/Blazor.MonoRuntime.targets | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 915ec80391b3..3c7d12656192 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -82,6 +82,8 @@ <!-- /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> @@ -159,7 +161,7 @@ <Target Name="_ResolveBlazorOutputsWhenLinked" Condition="'$(BlazorLinkOnBuild)' == 'true'" - DependsOnTargets="_GenerateBlazorLinkerDescriptor;_LinkBlazorApplication"> + 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)"> @@ -167,6 +169,28 @@ </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> + + </Target> + <UsingTask TaskName="BlazorCreateRootDescriptorFile" AssemblyFile="$(BlazorTasksPath)" /> <Target Name="_GenerateBlazorLinkerDescriptor" Inputs="@(IntermediateAssembly)" @@ -186,9 +210,22 @@ </ItemGroup> </Target> - <UsingTask TaskName="BlazorILLink" AssemblyFile="$(BlazorTasksPath)" /> <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> + <UsingTask TaskName="BlazorILLink" AssemblyFile="$(BlazorTasksPath)" /> <Target Name="_LinkBlazorApplication" Inputs="$(ProjectAssetsFile); @@ -197,22 +234,6 @@ $(MSBuildAllProjects)" Outputs="$(_BlazorLinkerOutputCache)"> - <ItemGroup> - <_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)" /> - <_BlazorDependencyAssembly IsLinkable="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('System.'))" /> - <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))" /> - <_BlazorDependencyAssembly IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.'))" /> - <!-- Any assembly from a package reference that starts with System. file name is allowed to be linked --> - <_BlazorRuntimeCopyLocalItems Include="@(RuntimeCopyLocalItems)" IsLinkable="$([System.String]::Copy('%(FileName)').StartsWith('System.'))" /> - - <_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" /> - <_BlazorAssemblyToLink Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' == 'true'" /> - - <_BlazorLinkerRoot Include="@(IntermediateAssembly)" /> - <_BlazorLinkerRoot Include="@(_BlazorUserRuntimeAssembly)" /> - <_BlazorLinkerRoot Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' != 'true'" /> - </ItemGroup> - <PropertyGroup> <_BlazorLinkerAdditionalOptions>-l $(MonoLinkerI18NAssemblies) $(AdditionalMonoLinkerOptions)</_BlazorLinkerAdditionalOptions> </PropertyGroup> @@ -234,15 +255,6 @@ <_DotNetHostFileName Condition=" '$(OS)' == 'Windows_NT' ">dotnet.exe</_DotNetHostFileName> </PropertyGroup> - <PropertyGroup> - <_TypeGranularityLinkingConfig>$(BlazorIntermediateOutputPath)linker.typegranularityconfig.xml</_TypeGranularityLinkingConfig> - </PropertyGroup> - <GenerateTypeGranularityLinkingConfig Assemblies="@(_BlazorAssemblyToLink->WithMetadataValue('TypeGranularity', 'true'))" OutputPath="$(_TypeGranularityLinkingConfig)" /> - <ItemGroup> - <BlazorLinkerDescriptor Include="$(_TypeGranularityLinkingConfig)" /> - <FileWrites Include="$(_TypeGranularityLinkingConfig)" /> - </ItemGroup> - <BlazorILLink ILLinkPath="$(MonoLinkerPath)" AssemblyPaths="@(_BlazorAssemblyToLink)" From 17b1dc9841961850db8c938a5ac09f9f97f73c8e Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 10 Dec 2019 15:33:45 -0800 Subject: [PATCH 046/322] Add a benchmarking app for Blazor Wasm --- .../wwwroot/benchmarks/index.js | 6 - src/Components/Components.sln | 53 +++-- src/Components/ComponentsNoDeps.slnf | 6 +- .../Directory.Build.props | 0 .../Directory.Build.targets | 0 .../{ => BlazingPizza.Server}/NuGet.config | 0 .../Driver/BenchmarkMeasurement.cs | 14 ++ .../Driver/BenchmarkMetadata.cs | 14 ++ .../Driver/BenchmarkOutput.cs | 14 ++ .../Driver/BenchmarkResult.cs | 13 ++ .../Driver/BenchmarkResultsStartup.cs | 35 +++ .../Wasm.Performance/Driver/Program.cs | 210 +++++++++++++++++ .../Wasm.Performance/Driver/Selenium.cs | 99 ++++++++ .../Driver/Wasm.Performance.Driver.csproj | 23 ++ .../Wasm.Performance/Driver/appsettings.json | 8 + .../benchmarkapps/Wasm.Performance/README.md | 18 ++ .../Wasm.Performance/TestApp}/App.razor | 0 .../TestApp}/BenchmarkEvent.cs | 2 +- .../TestApp}/Pages/Index.razor | 0 .../TestApp}/Pages/Json.razor | 0 .../TestApp}/Pages/RenderList.razor | 0 .../TestApp}/Pages/_Imports.razor | 0 .../Wasm.Performance/TestApp}/Program.cs | 2 +- .../TestApp}/Shared/MainLayout.razor | 0 .../Wasm.Performance/TestApp}/Startup.cs | 2 +- .../TestApp/Wasm.Performance.TestApp.csproj} | 2 +- .../Wasm.Performance/TestApp}/_Imports.razor | 4 +- .../TestApp}/wwwroot/benchmarks/appStartup.js | 0 .../TestApp/wwwroot/benchmarks/index.js | 38 ++++ .../wwwroot/benchmarks/jsonHandling.js | 0 .../wwwroot/benchmarks/jsonHandlingData.js | 0 .../wwwroot/benchmarks/lib/bootstrap.min.css | 0 .../benchmarks/lib/minibench/README.md | 0 .../benchmarks/lib/minibench/minibench.js | 215 ++++-------------- .../benchmarks/lib/minibench/minibench.ui.js | 191 ++++++++++++++++ .../benchmarks/lib/minibench/style.css | 0 .../TestApp}/wwwroot/benchmarks/renderList.js | 0 .../benchmarks/util/BenchmarkEvents.js | 0 .../wwwroot/benchmarks/util/BlazorApp.js | 0 .../TestApp}/wwwroot/benchmarks/util/DOM.js | 0 .../TestApp}/wwwroot/blazor-frame.html | 0 .../TestApp}/wwwroot/index.html | 0 .../Wasm.Performance/benchmarks.compose.json | 15 ++ .../benchmarkapps/Wasm.Performance/dockerfile | 32 +++ .../benchmarkapps/Wasm.Performance/exec.sh | 5 + .../Wasm.Performance/local.dockerfile | 7 + ...soft.AspNetCore.Components.E2ETests.csproj | 2 +- .../test/E2ETest/Tests/PerformanceTest.cs | 4 +- 48 files changed, 821 insertions(+), 213 deletions(-) delete mode 100644 src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/index.js rename src/Components/benchmarkapps/{ => BlazingPizza.Server}/Directory.Build.props (100%) rename src/Components/benchmarkapps/{ => BlazingPizza.Server}/Directory.Build.targets (100%) rename src/Components/benchmarkapps/{ => BlazingPizza.Server}/NuGet.config (100%) create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMeasurement.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMetadata.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkOutput.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Driver/appsettings.json create mode 100644 src/Components/benchmarkapps/Wasm.Performance/README.md rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/App.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/BenchmarkEvent.cs (89%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Pages/Index.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Pages/Json.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Pages/RenderList.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Pages/_Imports.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Program.cs (91%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Shared/MainLayout.razor (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/Startup.cs (90%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj => benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj} (88%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/_Imports.razor (56%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/appStartup.js (100%) create mode 100644 src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/jsonHandling.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/jsonHandlingData.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/lib/bootstrap.min.css (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/lib/minibench/README.md (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/lib/minibench/minibench.js (58%) create mode 100644 src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.ui.js rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/lib/minibench/style.css (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/renderList.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/util/BenchmarkEvents.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/util/BlazorApp.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/benchmarks/util/DOM.js (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/blazor-frame.html (100%) rename src/Components/{Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance => benchmarkapps/Wasm.Performance/TestApp}/wwwroot/index.html (100%) create mode 100644 src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json create mode 100644 src/Components/benchmarkapps/Wasm.Performance/dockerfile create mode 100644 src/Components/benchmarkapps/Wasm.Performance/exec.sh create mode 100644 src/Components/benchmarkapps/Wasm.Performance/local.dockerfile diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/index.js b/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/index.js deleted file mode 100644 index 4600066f3872..000000000000 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { HtmlUI } from './lib/minibench/minibench.js'; -import './appStartup.js'; -import './renderList.js'; -import './jsonHandling.js'; - -new HtmlUI('E2E Performance', '#display'); diff --git a/src/Components/Components.sln b/src/Components/Components.sln index 91278955cf7b..c88695cf66e3 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -21,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DevServer", "Blazor\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj", "{A6C8050D-7C18-4585-ADCF-833AC1765847}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.E2EPerformance", "Blazor\testassets\Microsoft.AspNetCore.Blazor.E2EPerformance\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj", "{08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{A7ABAC29-F73F-456D-AE54-46842CFC2E10}" @@ -238,8 +236,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ignitor", "Ignitor\src\Igni EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ignitor.Test", "Ignitor\test\Ignitor.Test.csproj", "{F31E8118-014E-4CCE-8A48-5282F7B9BB3E}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{FD9BD646-9D50-42ED-A3E1-90558BA0C6B2}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation", "Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "{B70F90C7-2696-4050-B24E-BF0308F4E059}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{A5617A9D-C71E-44DE-936C-27611EB40A02}" @@ -250,6 +246,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{F2E27E1C-2E47-42C1-9AC7-36265A381717}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{CCC82E97-7B58-43E2-BBBD-23D82F926367}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wasm.Performance", "Wasm.Performance", "{F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.Driver", "benchmarkapps\Wasm.Performance\Driver\Wasm.Performance.Driver.csproj", "{CA9948CA-B3FA-4C2E-A726-5E47BAD19457}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -344,18 +348,6 @@ Global {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x64.Build.0 = Release|Any CPU {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x86.ActiveCfg = Release|Any CPU {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x86.Build.0 = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|x64.ActiveCfg = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|x64.Build.0 = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|x86.ActiveCfg = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Debug|x86.Build.0 = Debug|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|Any CPU.Build.0 = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|x64.ActiveCfg = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|x64.Build.0 = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|x86.ActiveCfg = Release|Any CPU - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB}.Release|x86.Build.0 = Release|Any CPU {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -1532,6 +1524,30 @@ Global {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x64.Build.0 = Release|Any CPU {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.ActiveCfg = Release|Any CPU {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.Build.0 = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x64.Build.0 = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x86.Build.0 = Debug|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|Any CPU.Build.0 = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x64.ActiveCfg = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x64.Build.0 = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x86.ActiveCfg = Release|Any CPU + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x86.Build.0 = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x64.ActiveCfg = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x64.Build.0 = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x86.Build.0 = Debug|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|Any CPU.Build.0 = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x64.ActiveCfg = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x64.Build.0 = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x86.ActiveCfg = Release|Any CPU + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1544,7 +1560,6 @@ Global {E8AD67A4-77D3-4B85-AE19-4711388B62B1} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {E38FDBB0-08C1-444E-A449-69C8A59D721B} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A6C8050D-7C18-4585-ADCF-833AC1765847} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {08773DD6-6FED-4BF2-BD9F-C19D2CF919BB} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A7ABAC29-F73F-456D-AE54-46842CFC2E10} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {FD37F740-A654-4117-BFB6-9112CE4C1D3B} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10} @@ -1641,12 +1656,14 @@ Global {BBF37AF9-8290-4B70-8BA8-0F6017B3B620} = {46E4300C-5726-4108-B9A2-18BB94EB26ED} {CD0EF85C-4187-4515-A355-E5A0D4485F40} = {BDE2397D-C53A-4783-8B3A-1F54F48A6926} {F31E8118-014E-4CCE-8A48-5282F7B9BB3E} = {BDE2397D-C53A-4783-8B3A-1F54F48A6926} - {FD9BD646-9D50-42ED-A3E1-90558BA0C6B2} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {B70F90C7-2696-4050-B24E-BF0308F4E059} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} {F2E27E1C-2E47-42C1-9AC7-36265A381717} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} + {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} = {CCC82E97-7B58-43E2-BBBD-23D82F926367} + {CA9948CA-B3FA-4C2E-A726-5E47BAD19457} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} + {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE} diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf index 61501c51010a..7e09eeea25ce 100644 --- a/src/Components/ComponentsNoDeps.slnf +++ b/src/Components/ComponentsNoDeps.slnf @@ -13,14 +13,12 @@ "Blazor\\DevServer\\src\\Microsoft.AspNetCore.Blazor.DevServer.csproj", "Blazor\\Http\\src\\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "Blazor\\Http\\test\\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", + "Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj", "Blazor\\Server\\src\\Microsoft.AspNetCore.Blazor.Server.csproj", - "Blazor\\Templates\\src\\Microsoft.AspNetCore.Blazor.Templates.csproj", "Blazor\\Validation\\src\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "Blazor\\Validation\\test\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", - "Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj", "Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", "Blazor\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj", - "Blazor\\testassets\\Microsoft.AspNetCore.Blazor.E2EPerformance\\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj", "Blazor\\testassets\\MonoSanityClient\\MonoSanityClient.csproj", "Blazor\\testassets\\MonoSanity\\MonoSanity.csproj", "Blazor\\testassets\\StandaloneApp\\StandaloneApp.csproj", @@ -36,6 +34,8 @@ "Server\\test\\Microsoft.AspNetCore.Components.Server.Tests.csproj", "Web\\src\\Microsoft.AspNetCore.Components.Web.csproj", "Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj", + "benchmarkapps\\Wasm.Performance\\Driver\\Wasm.Performance.Driver.csproj", + "benchmarkapps\\Wasm.Performance\\TestApp\\Wasm.Performance.TestApp.csproj", "test\\E2ETest\\Microsoft.AspNetCore.Components.E2ETests.csproj", "test\\testassets\\BasicTestApp\\BasicTestApp.csproj", "test\\testassets\\TestContentPackage\\TestContentPackage.csproj", diff --git a/src/Components/benchmarkapps/Directory.Build.props b/src/Components/benchmarkapps/BlazingPizza.Server/Directory.Build.props similarity index 100% rename from src/Components/benchmarkapps/Directory.Build.props rename to src/Components/benchmarkapps/BlazingPizza.Server/Directory.Build.props diff --git a/src/Components/benchmarkapps/Directory.Build.targets b/src/Components/benchmarkapps/BlazingPizza.Server/Directory.Build.targets similarity index 100% rename from src/Components/benchmarkapps/Directory.Build.targets rename to src/Components/benchmarkapps/BlazingPizza.Server/Directory.Build.targets diff --git a/src/Components/benchmarkapps/NuGet.config b/src/Components/benchmarkapps/BlazingPizza.Server/NuGet.config similarity index 100% rename from src/Components/benchmarkapps/NuGet.config rename to src/Components/benchmarkapps/BlazingPizza.Server/NuGet.config diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMeasurement.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMeasurement.cs new file mode 100644 index 000000000000..62016cf630e6 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMeasurement.cs @@ -0,0 +1,14 @@ +// 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; + +namespace Wasm.Performance.Driver +{ + internal class BenchmarkMeasurement + { + public DateTime Timestamp { get; internal set; } + public string Name { get; internal set; } + public double Value { get; internal set; } + } +} \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMetadata.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMetadata.cs new file mode 100644 index 000000000000..ab98fef891b9 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkMetadata.cs @@ -0,0 +1,14 @@ +// 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 Wasm.Performance.Driver +{ + internal class BenchmarkMetadata + { + public string Source { get; set; } + public string Name { get; set; } + public string ShortDescription { get; set; } + public string LongDescription { get; set; } + public string Format { get; set; } + } +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkOutput.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkOutput.cs new file mode 100644 index 000000000000..7a32ce146d58 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkOutput.cs @@ -0,0 +1,14 @@ +// 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.Collections.Generic; + +namespace Wasm.Performance.Driver +{ + internal class BenchmarkOutput + { + public List<BenchmarkMetadata> Metadata { get; } = new List<BenchmarkMetadata>(); + + public List<BenchmarkMeasurement> Measurements { get; } = new List<BenchmarkMeasurement>(); + } +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs new file mode 100644 index 000000000000..3173341e4b86 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs @@ -0,0 +1,13 @@ +namespace Wasm.Performance.Driver +{ + class BenchmarkResult + { + public string Name { get; set; } + + public bool Success { get; set; } + + public int NumExecutions { get; set; } + + public double Duration { get; set; } + } +} \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs new file mode 100644 index 000000000000..1fa1f067a0d9 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Wasm.Performance.Driver +{ + public class BenchmarkDriverStartup + { + + public void ConfigureServices(IServiceCollection services) + { + services.AddCors(c => c.AddDefaultPolicy(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin())); + } + + public void Configure(IApplicationBuilder app) + { + app.UseCors(); + + app.Run(async request => + { + var result = await JsonSerializer.DeserializeAsync<List<BenchmarkResult>>(request.Request.Body, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }); + Program.SetBenchmarkResult(result); + }); + } + } +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs new file mode 100644 index 000000000000..8075d83bddad --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -0,0 +1,210 @@ +// 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.Runtime.ExceptionServices; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using DevHostServerProgram = Microsoft.AspNetCore.Blazor.DevServer.Server.Program; + +namespace Wasm.Performance.Driver +{ + public class Program + { + static readonly TimeSpan Timeout = TimeSpan.FromMinutes(3); + static TaskCompletionSource<List<BenchmarkResult>> benchmarkResult = new TaskCompletionSource<List<BenchmarkResult>>(); + + public static async Task<int> Main(string[] args) + { + var seleniumPort = 4444; + if (args.Length > 0) + { + if (!int.TryParse(args[0], out seleniumPort)) + { + Console.Error.WriteLine("Usage Driver <selenium-port>"); + return 1; + } + } + + using var browser = await Selenium.CreateBrowser(seleniumPort); + + using var testApp = StartTestApp(); + using var benchmarkReceiver = StartBenchmarkResultReceiver(); + + var testAppUrl = GetListeningUrl(testApp); + var receiverUrl = GetListeningUrl(benchmarkReceiver); + + Console.WriteLine($"Test app listening at {testAppUrl}."); + + var launchUrl = $"{testAppUrl}?resultsUrl={UrlEncoder.Default.Encode(receiverUrl)}#automated"; + browser.Url = launchUrl; + browser.Navigate(); + + var cancellationToken = new CancellationTokenSource(Timeout); + cancellationToken.Token.Register(() => benchmarkResult.TrySetException(new TimeoutException($"Timed out after {Timeout}"))); + + var results = await benchmarkResult.Task; + FormatAsBenchmarksOutput(results); + + Console.WriteLine("Done executing benchmark"); + return 0; + } + + internal static void SetBenchmarkResult(List<BenchmarkResult> result) + { + benchmarkResult.TrySetResult(result); + } + + private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) + { + // Sample of the the format: https://github.com/aspnet/Benchmarks/blob/e55f9e0312a7dd019d1268c1a547d1863f0c7237/src/Benchmarks/Program.cs#L51-L67 + var output = new BenchmarkOutput(); + foreach (var result in results) + { + output.Metadata.Add(new BenchmarkMetadata + { + Source = "BlazorWasm", + Name = result.Name, + ShortDescription = $"{result.Name} Duration", + LongDescription = $"{result.Name} Duration", + Format = "n2" + }); + + output.Measurements.Add(new BenchmarkMeasurement + { + Timestamp = DateTime.UtcNow, + Name = result.Name, + Value = result.Duration, + }); + } + + // Statistics about publish sizes + output.Metadata.Add(new BenchmarkMetadata + { + Source = "BlazorWasm", + Name = "Publish size (linked)", + ShortDescription = "Publish size - linked app (MB)", + LongDescription = "Publish size - linked app (MB)", + Format = "n2", + }); + + var testAssembly = typeof(TestApp.Startup).Assembly; + var testApp = new DirectoryInfo(Path.Combine( + Path.GetDirectoryName(testAssembly.Location), + testAssembly.GetName().Name)); + + output.Measurements.Add(new BenchmarkMeasurement + { + Timestamp = DateTime.UtcNow, + Name = "Publish size (linked)", + Value = GetDirectorySize(testApp) / 1024, + }); + + Console.WriteLine("#StartJobStatistics"); + Console.WriteLine(JsonSerializer.Serialize(output)); + Console.WriteLine("#EndJobStatistics"); + } + + static IHost StartTestApp() + { + var args = new[] + { + "--urls", "http://127.0.0.1:0", + "--applicationpath", typeof(TestApp.Startup).Assembly.Location, + }; + + var host = DevHostServerProgram.BuildWebHost(args); + RunInBackgroundThread(host.Start); + return host; + } + + static IHost StartBenchmarkResultReceiver() + { + var args = new[] + { + "--urls", "http://127.0.0.1:0", + }; + + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(builder => builder.UseStartup<BenchmarkDriverStartup>()) + .Build(); + + RunInBackgroundThread(host.Start); + return host; + } + + static void RunInBackgroundThread(Action action) + { + var isDone = new ManualResetEvent(false); + + ExceptionDispatchInfo edi = null; + Task.Run(() => + { + try + { + action(); + } + catch (Exception ex) + { + edi = ExceptionDispatchInfo.Capture(ex); + } + + isDone.Set(); + }); + + if (!isDone.WaitOne(Timeout)) + { + throw new TimeoutException("Timed out waiting for: " + action); + } + + if (edi != null) + { + throw edi.SourceException; + } + } + + static string GetListeningUrl(IHost testApp) + { + return testApp.Services.GetRequiredService<IServer>() + .Features + .Get<IServerAddressesFeature>() + .Addresses + .First(); + } + + static long GetDirectorySize(DirectoryInfo directory) + { + // This can happen if you run the app without publishing it. + if (!directory.Exists) + { + return 0; + } + + long size = 0; + foreach (var item in directory.EnumerateFileSystemInfos()) + { + if (item is FileInfo fileInfo) + { + size += fileInfo.Length; + } + else if (item is DirectoryInfo directoryInfo) + { + size += GetDirectorySize(directoryInfo); + } + } + + return size; + } + } +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs new file mode 100644 index 000000000000..169d3735a12a --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs @@ -0,0 +1,99 @@ +// 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.Net; +using System.Net.Http; +using System.Threading.Tasks; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Remote; + +namespace Wasm.Performance.Driver +{ + class Selenium + { + static bool RunHeadlessBrowser = true; + + private static async ValueTask<Uri> WaitForServerAsync(int port) + { + var uri = new UriBuilder("http", "localhost", port, "/wd/hub/").Uri; + var httpClient = new HttpClient + { + BaseAddress = uri, + Timeout = TimeSpan.FromSeconds(1), + }; + + Console.WriteLine($"Attempting to connect to Selenium Server running at {uri}"); + + const int MaxRetries = 30; + var retries = 0; + + while (retries < MaxRetries) + { + retries++; + try + { + var response = (await httpClient.GetAsync("status")).EnsureSuccessStatusCode(); + Console.WriteLine("Connected to Selenium"); + return uri; + } + catch + { + if (retries == 1) + { + Console.WriteLine("Could not connect to selenium-server. Has it been started as yet?"); + } + } + + await Task.Delay(1000); + } + + throw new Exception($"Unable to connect to selenium-server at {uri}"); + } + + public static async Task<RemoteWebDriver> CreateBrowser(int port) + { + var uri = await WaitForServerAsync(port); + + var options = new ChromeOptions(); + + if (RunHeadlessBrowser) + { + options.AddArgument("--headless"); + } + + options.SetLoggingPreference(LogType.Browser, LogLevel.All); + + var attempt = 0; + const int MaxAttempts = 3; + do + { + try + { + // The driver opens the browser window and tries to connect to it on the constructor. + // Under heavy load, this can cause issues + // To prevent this we let the client attempt several times to connect to the server, increasing + // the max allowed timeout for a command on each attempt linearly. + var driver = new RemoteWebDriver( + uri, + options.ToCapabilities(), + TimeSpan.FromSeconds(60).Add(TimeSpan.FromSeconds(attempt * 60))); + + driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1); + + return driver; + } + catch (Exception ex) + { + Console.WriteLine($"Error initializing RemoteWebDriver: {ex.Message}"); + } + + attempt++; + + } while (attempt < MaxAttempts); + + throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive"); + } + } +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj b/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj new file mode 100644 index 000000000000..cf35be4e007e --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj @@ -0,0 +1,23 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <!-- Intentionally pinned this to .NET Core 3.1 since that's the supported version in the docker image --> + <TargetFramework>netcoreapp3.1</TargetFramework> + + <UseLatestAspNetCoreReference>true</UseLatestAspNetCoreReference> + <OutputType>exe</OutputType> + + <!-- WebDriver is not strong-named, so this test project cannot be strong named either. --> + <SignAssembly>false</SignAssembly> + </PropertyGroup> + + <ItemGroup> + <Reference Include="Selenium.Support" /> + <Reference Include="Selenium.WebDriver" /> + <ProjectReference Include="..\..\..\Blazor\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj" /> + <ProjectReference Include="..\TestApp\Wasm.Performance.TestApp.csproj" /> + + <Content Include="appsettings.json" CopyToPublishDirectory="PreserveNewest" /> + </ItemGroup> + +</Project> diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/appsettings.json b/src/Components/benchmarkapps/Wasm.Performance/Driver/appsettings.json new file mode 100644 index 000000000000..bed61b254f6f --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Warning" + } + } +} \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/README.md b/src/Components/benchmarkapps/Wasm.Performance/README.md new file mode 100644 index 000000000000..ac0f59e5700a --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/README.md @@ -0,0 +1,18 @@ +## Blazor WASM benchmarks + +These projects assist in Benchmarking Components. +See https://github.com/aspnet/Benchmarks#benchmarks for usage guidance on using the Benchmarking tool with your application + +### Running the benchmarks + +The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. The Driver is an app that speaks the Benchmark protocol. You generally do not need to run the Driver locally, but if you were to do so, you require docker. Here are the commands you would need to run it locally: + +1. `dotnet publish -c Release -r linux-x64 Driver/Wasm.Performance.Driver.csproj` +2. `docker build -t blazor-local -f ./local.dockerfile . ` +3. `docker run -it blazor-local` + +To run the benchmark app in the Benchmark server, run + +``` +dotnet run -- --config aspnetcore/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json --services.blazorwasmbenchmark.endpoints <BenchmarkServerUri> +``` \ No newline at end of file diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/App.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/App.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/BenchmarkEvent.cs b/src/Components/benchmarkapps/Wasm.Performance/TestApp/BenchmarkEvent.cs similarity index 89% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/BenchmarkEvent.cs rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/BenchmarkEvent.cs index bdf98fd38879..81cd361dce7c 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/BenchmarkEvent.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/BenchmarkEvent.cs @@ -3,7 +3,7 @@ using Microsoft.JSInterop; -namespace Microsoft.AspNetCore.Blazor.E2EPerformance +namespace Wasm.Performance.TestApp { public static class BenchmarkEvent { diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/Index.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/Index.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/Index.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/Index.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/Json.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/Json.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/Json.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/Json.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/RenderList.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/RenderList.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/RenderList.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/RenderList.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/_Imports.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/_Imports.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Pages/_Imports.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Pages/_Imports.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs similarity index 91% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Program.cs rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs index f498eb0222b9..403bc37c9c35 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Blazor.Hosting; -namespace Microsoft.AspNetCore.Blazor.E2EPerformance +namespace Wasm.Performance.TestApp { public class Program { diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Shared/MainLayout.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Shared/MainLayout.razor similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Shared/MainLayout.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Shared/MainLayout.razor diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Startup.cs b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs similarity index 90% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Startup.cs rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs index 7422cd806cff..c79b0efb8c38 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Startup.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Components.Builder; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.AspNetCore.Blazor.E2EPerformance +namespace Wasm.Performance.TestApp { public class Startup { diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj similarity index 88% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj index 140762810fb5..3fb5a922a3fd 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/Microsoft.AspNetCore.Blazor.E2EPerformance.csproj +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk.Web"> +<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/_Imports.razor b/src/Components/benchmarkapps/Wasm.Performance/TestApp/_Imports.razor similarity index 56% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/_Imports.razor rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/_Imports.razor index dc263c9383a5..fef56339a95f 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/_Imports.razor +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/_Imports.razor @@ -2,5 +2,5 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop -@using Microsoft.AspNetCore.Blazor.E2EPerformance -@using Microsoft.AspNetCore.Blazor.E2EPerformance.Shared +@using Wasm.Performance.TestApp +@using Wasm.Performance.TestApp.Shared diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/appStartup.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/appStartup.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js new file mode 100644 index 000000000000..6a1ba57f8222 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js @@ -0,0 +1,38 @@ +import { groups, BenchmarkEvent, onBenchmarkEvent } from './lib/minibench/minibench.js'; +import { HtmlUI } from './lib/minibench/minibench.ui.js'; +// import './appStartup.js'; +// import './renderList.js'; +import './jsonHandling.js'; + +new HtmlUI('E2E Performance', '#display'); + +if (location.href.indexOf('#automated') !== -1) { + const query = new URLSearchParams(window.location.search); + const group = query.get('group'); + const resultsUrl = query.get('resultsUrl'); + + groups.filter(g => !group || g.name === group).forEach(g => g.runAll()); + + const benchmarksResults = []; + onBenchmarkEvent(async (status, args) => { + switch (status) { + case BenchmarkEvent.runStarted: + benchmarksResults.length = 0; + break; + case BenchmarkEvent.benchmarkCompleted: + case BenchmarkEvent.benchmarkError: + benchmarksResults.push(args); + break; + case BenchmarkEvent.runCompleted: + if (resultsUrl) { + await fetch(resultsUrl, { + method: 'post', + body: JSON.stringify(benchmarksResults) + }); + } + break; + default: + throw new Error(`Unknown status: ${status}`); + } + }) +} diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/jsonHandling.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/jsonHandling.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/jsonHandlingData.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandlingData.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/jsonHandlingData.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandlingData.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/bootstrap.min.css b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/bootstrap.min.css similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/bootstrap.min.css rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/bootstrap.min.css diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/README.md b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/README.md similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/README.md rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/README.md diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/minibench.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js similarity index 58% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/minibench.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js index 82144199822c..6d13c5657791 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/minibench.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js @@ -66,7 +66,7 @@ window.addEventListener('message', evt => { To work around browsers' current nonsupport for high-resolution timers (since Spectre etc.), the approach used here is to group executions into blocks of roughly fixed duration. - + - In each block, we execute the test code as many times as we can until the end of the block duration, without even yielding the thread if it's a synchronous call. We count how many executions completed. It @@ -82,7 +82,7 @@ window.addEventListener('message', evt => { during which there was no unrelated GC cycle or other background contention. - We keep running blocks until some larger timeout occurs *and* we've done at least some minimum number of executions. - + Note that this approach does *not* allow for per-execution setup/teardown logic whose timing is separated from the code under test. Because of the low timer precision, there would be no way to separate the setup duration @@ -174,10 +174,23 @@ class Benchmark extends EventEmitter { } run(runOptions) { + if (reportBenchmarkEvent) { + const areAllIdle = groups.reduce( + (prev, next) => prev && next.status === BenchmarkStatus.idle, + true + ); + + if (areAllIdle) { + // This is the first test being run from the idle state + reportBenchmarkEvent(BenchmarkEvent.runStarted); + } + } + this._currentRunWasAborted = false; if (this._state.status === BenchmarkStatus.idle) { this._updateState({ status: BenchmarkStatus.queued }); this.workQueueCancelHandle = addToWorkQueue(async () => { + try { if (!(runOptions && runOptions.skipGroupSetup)) { await this._group.runSetup(); @@ -192,10 +205,13 @@ class Benchmark extends EventEmitter { await this._group.runTeardown(); } + reportBenchmarkEvent(BenchmarkEvent.benchmarkCompleted, { 'name': this.name, success: true, numExecutions: this._state.numExecutions, duration: this._state.estimatedExecutionDurationMs }); + this._updateState({ status: BenchmarkStatus.idle }); } catch (ex) { this._updateState({ status: BenchmarkStatus.error }); console.error(ex); + reportBenchmarkEvent(BenchmarkEvent.benchmarkError, { 'name': this.name, success: false }); } }); } @@ -237,6 +253,13 @@ const BenchmarkStatus = { error: 3, }; +const BenchmarkEvent = { + runStarted: 0, + benchmarkCompleted : 1, + benchmarkError: 2, + runCompleted: 3, +} + class Group extends EventEmitter { constructor(name) { super(); @@ -279,6 +302,7 @@ class Group extends EventEmitter { } const groups = []; +let reportBenchmarkEvent; function group(name, configure) { groups.push(new Group(name)); @@ -298,184 +322,21 @@ function teardown(fn) { groups[groups.length - 1].teardown = fn; } -class BenchmarkDisplay { - constructor(htmlUi, benchmark) { - this.benchmark = benchmark; - this.elem = document.createElement('tr'); - - const headerCol = this.elem.appendChild(document.createElement('th')); - headerCol.className = 'pl-4'; - headerCol.textContent = benchmark.name; - headerCol.setAttribute('scope', 'row'); - - const progressCol = this.elem.appendChild(document.createElement('td')); - this.numExecutionsText = progressCol.appendChild(document.createTextNode('')); - - const timingCol = this.elem.appendChild(document.createElement('td')); - this.executionDurationText = timingCol.appendChild(document.createElement('span')); - - const runCol = this.elem.appendChild(document.createElement('td')); - runCol.className = 'pr-4'; - runCol.setAttribute('align', 'right'); - this.runButton = document.createElement('a'); - this.runButton.className = 'run-button'; - runCol.appendChild(this.runButton); - this.runButton.textContent = 'Run'; - this.runButton.onclick = evt => { - evt.preventDefault(); - this.benchmark.run(htmlUi.globalRunOptions); - }; +function onBenchmarkEvent(fn) { + reportBenchmarkEvent = fn; - benchmark.on('changed', state => this.updateDisplay(state)); - this.updateDisplay(this.benchmark.state); - } + groups.forEach(group$$1 => { + group$$1.on('changed', () => { + const areAllIdle = groups.reduce( + (prev, next) => prev && next.status === BenchmarkStatus.idle, + true + ); - updateDisplay(state) { - const benchmark = this.benchmark; - this.elem.className = rowClass(state.status); - this.runButton.textContent = runButtonText(state.status); - this.numExecutionsText.textContent = state.numExecutions - ? `Executions: ${state.numExecutions}` : ''; - this.executionDurationText.innerHTML = state.estimatedExecutionDurationMs - ? `Duration: <b>${parseFloat(state.estimatedExecutionDurationMs.toPrecision(3))}ms</b>` : ''; - if (state.status === BenchmarkStatus.idle) { - this.runButton.setAttribute('href', ''); - } else { - this.runButton.removeAttribute('href'); - if (state.status === BenchmarkStatus.error) { - this.numExecutionsText.textContent = 'Error - see console'; + if (areAllIdle) { + fn(BenchmarkEvent.runCompleted); } - } - } -} - -function runButtonText(status) { - switch (status) { - case BenchmarkStatus.idle: - case BenchmarkStatus.error: - return 'Run'; - case BenchmarkStatus.queued: - return 'Waiting...'; - case BenchmarkStatus.running: - return 'Running...'; - default: - throw new Error(`Unknown status: ${status}`); - } -} - -function rowClass(status) { - switch (status) { - case BenchmarkStatus.idle: - return 'benchmark-idle'; - case BenchmarkStatus.queued: - return 'benchmark-waiting'; - case BenchmarkStatus.running: - return 'benchmark-running'; - case BenchmarkStatus.error: - return 'benchmark-error'; - default: - throw new Error(`Unknown status: ${status}`); - } -} - -class GroupDisplay { - constructor(htmlUi, group) { - this.group = group; - - this.elem = document.createElement('div'); - this.elem.className = 'my-3 py-2 bg-white rounded shadow-sm'; - - const headerContainer = this.elem.appendChild(document.createElement('div')); - headerContainer.className = 'd-flex align-items-baseline px-4'; - const header = headerContainer.appendChild(document.createElement('h5')); - header.className = 'py-2'; - header.textContent = group.name; - - this.runButton = document.createElement('a'); - this.runButton.className = 'ml-auto run-button'; - this.runButton.setAttribute('href', ''); - headerContainer.appendChild(this.runButton); - this.runButton.textContent = 'Run all'; - this.runButton.onclick = evt => { - evt.preventDefault(); - group.runAll(htmlUi.globalRunOptions); - }; - - const table = this.elem.appendChild(document.createElement('table')); - table.className = 'table mb-0 benchmarks'; - const tbody = table.appendChild(document.createElement('tbody')); - - group.benchmarks.forEach(benchmark => { - const benchmarkDisplay = new BenchmarkDisplay(htmlUi, benchmark); - tbody.appendChild(benchmarkDisplay.elem); }); - - group.on('changed', () => this.updateDisplay()); - this.updateDisplay(); - } - - updateDisplay() { - const canRun = this.group.status === BenchmarkStatus.idle; - this.runButton.style.display = canRun ? 'block' : 'none'; - } -} - -class HtmlUI { - constructor(title, selector) { - this.containerElement = document.querySelector(selector); - - const headerDiv = this.containerElement.appendChild(document.createElement('div')); - headerDiv.className = 'd-flex align-items-center'; - - const header = headerDiv.appendChild(document.createElement('h2')); - header.className = 'mx-3 flex-grow-1'; - header.textContent = title; - - const verifyCheckboxLabel = document.createElement('label'); - verifyCheckboxLabel.className = 'ml-auto mr-5'; - headerDiv.appendChild(verifyCheckboxLabel); - this.verifyCheckbox = verifyCheckboxLabel.appendChild(document.createElement('input')); - this.verifyCheckbox.type = 'checkbox'; - this.verifyCheckbox.className = 'mr-2'; - verifyCheckboxLabel.appendChild(document.createTextNode('Verify only')); - - this.runButton = document.createElement('button'); - this.runButton.className = 'btn btn-success ml-auto px-4 run-button'; - headerDiv.appendChild(this.runButton); - this.runButton.textContent = 'Run all'; - this.runButton.onclick = () => { - groups.forEach(g => g.runAll(this.globalRunOptions)); - }; - - this.stopButton = document.createElement('button'); - this.stopButton.className = 'btn btn-danger ml-auto px-4 stop-button'; - headerDiv.appendChild(this.stopButton); - this.stopButton.textContent = 'Stop'; - this.stopButton.onclick = () => { - groups.forEach(g => g.stopAll()); - }; - - groups.forEach(group$$1 => { - const groupDisplay = new GroupDisplay(this, group$$1); - this.containerElement.appendChild(groupDisplay.elem); - group$$1.on('changed', () => this.updateDisplay()); - }); - - this.updateDisplay(); - } - - updateDisplay() { - const areAllIdle = groups.reduce( - (prev, next) => prev && next.status === BenchmarkStatus.idle, - true - ); - this.runButton.style.display = areAllIdle ? 'block' : 'none'; - this.stopButton.style.display = areAllIdle ? 'none' : 'block'; - } - - get globalRunOptions() { - return { verifyOnly: this.verifyCheckbox.checked }; - } + }); } /** @@ -483,4 +344,4 @@ class HtmlUI { * https://github.com/SteveSanderson/minibench */ -export { group, benchmark, setup, teardown, HtmlUI }; +export { groups, group, benchmark, setup, teardown, onBenchmarkEvent, BenchmarkEvent, BenchmarkStatus }; diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.ui.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.ui.js new file mode 100644 index 000000000000..4384b7660b74 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.ui.js @@ -0,0 +1,191 @@ +/** minibench - https://github.com/SteveSanderson/minibench */ + +import { groups, BenchmarkStatus } from './minibench.js'; + +class BenchmarkDisplay { + constructor(htmlUi, benchmark) { + this.benchmark = benchmark; + this.elem = document.createElement('tr'); + + const headerCol = this.elem.appendChild(document.createElement('th')); + headerCol.className = 'pl-4'; + headerCol.textContent = benchmark.name; + headerCol.setAttribute('scope', 'row'); + + const progressCol = this.elem.appendChild(document.createElement('td')); + this.numExecutionsText = progressCol.appendChild(document.createTextNode('')); + + const timingCol = this.elem.appendChild(document.createElement('td')); + this.executionDurationText = timingCol.appendChild(document.createElement('span')); + + const runCol = this.elem.appendChild(document.createElement('td')); + runCol.className = 'pr-4'; + runCol.setAttribute('align', 'right'); + this.runButton = document.createElement('a'); + this.runButton.className = 'run-button'; + runCol.appendChild(this.runButton); + this.runButton.textContent = 'Run'; + this.runButton.onclick = evt => { + evt.preventDefault(); + this.benchmark.run(htmlUi.globalRunOptions); + }; + + benchmark.on('changed', state => this.updateDisplay(state)); + this.updateDisplay(this.benchmark.state); + } + + updateDisplay(state) { + const benchmark = this.benchmark; + this.elem.className = rowClass(state.status); + this.runButton.textContent = runButtonText(state.status); + this.numExecutionsText.textContent = state.numExecutions + ? `Executions: ${state.numExecutions}` : ''; + this.executionDurationText.innerHTML = state.estimatedExecutionDurationMs + ? `Duration: <b>${parseFloat(state.estimatedExecutionDurationMs.toPrecision(3))}ms</b>` : ''; + if (state.status === BenchmarkStatus.idle) { + this.runButton.setAttribute('href', ''); + } else { + this.runButton.removeAttribute('href'); + if (state.status === BenchmarkStatus.error) { + this.numExecutionsText.textContent = 'Error - see console'; + } + } + } +} + +function runButtonText(status) { + switch (status) { + case BenchmarkStatus.idle: + case BenchmarkStatus.error: + return 'Run'; + case BenchmarkStatus.queued: + return 'Waiting...'; + case BenchmarkStatus.running: + return 'Running...'; + default: + throw new Error(`Unknown status: ${status}`); + } +} + +function rowClass(status) { + switch (status) { + case BenchmarkStatus.idle: + return 'benchmark-idle'; + case BenchmarkStatus.queued: + return 'benchmark-waiting'; + case BenchmarkStatus.running: + return 'benchmark-running'; + case BenchmarkStatus.error: + return 'benchmark-error'; + default: + throw new Error(`Unknown status: ${status}`); + } +} + +class GroupDisplay { + constructor(htmlUi, group) { + this.group = group; + + this.elem = document.createElement('div'); + this.elem.className = 'my-3 py-2 bg-white rounded shadow-sm'; + + const headerContainer = this.elem.appendChild(document.createElement('div')); + headerContainer.className = 'd-flex align-items-baseline px-4'; + const header = headerContainer.appendChild(document.createElement('h5')); + header.className = 'py-2'; + header.textContent = group.name; + + this.runButton = document.createElement('a'); + this.runButton.className = 'ml-auto run-button'; + this.runButton.setAttribute('href', ''); + headerContainer.appendChild(this.runButton); + this.runButton.textContent = 'Run all'; + this.runButton.onclick = evt => { + evt.preventDefault(); + group.runAll(htmlUi.globalRunOptions); + }; + + const table = this.elem.appendChild(document.createElement('table')); + table.className = 'table mb-0 benchmarks'; + const tbody = table.appendChild(document.createElement('tbody')); + + group.benchmarks.forEach(benchmark => { + const benchmarkDisplay = new BenchmarkDisplay(htmlUi, benchmark); + tbody.appendChild(benchmarkDisplay.elem); + }); + + group.on('changed', () => this.updateDisplay()); + this.updateDisplay(); + } + + updateDisplay() { + const canRun = this.group.status === BenchmarkStatus.idle; + this.runButton.style.display = canRun ? 'block' : 'none'; + } +} + +class HtmlUI { + constructor(title, selector) { + this.containerElement = document.querySelector(selector); + + const headerDiv = this.containerElement.appendChild(document.createElement('div')); + headerDiv.className = 'd-flex align-items-center'; + + const header = headerDiv.appendChild(document.createElement('h2')); + header.className = 'mx-3 flex-grow-1'; + header.textContent = title; + + const verifyCheckboxLabel = document.createElement('label'); + verifyCheckboxLabel.className = 'ml-auto mr-5'; + headerDiv.appendChild(verifyCheckboxLabel); + this.verifyCheckbox = verifyCheckboxLabel.appendChild(document.createElement('input')); + this.verifyCheckbox.type = 'checkbox'; + this.verifyCheckbox.className = 'mr-2'; + verifyCheckboxLabel.appendChild(document.createTextNode('Verify only')); + + this.runButton = document.createElement('button'); + this.runButton.className = 'btn btn-success ml-auto px-4 run-button'; + headerDiv.appendChild(this.runButton); + this.runButton.textContent = 'Run all'; + this.runButton.setAttribute('id', 'runAll'); + this.runButton.onclick = () => { + groups.forEach(g => g.runAll(this.globalRunOptions)); + }; + + this.stopButton = document.createElement('button'); + this.stopButton.className = 'btn btn-danger ml-auto px-4 stop-button'; + headerDiv.appendChild(this.stopButton); + this.stopButton.textContent = 'Stop'; + this.stopButton.onclick = () => { + groups.forEach(g => g.stopAll()); + }; + + groups.forEach(group$$1 => { + const groupDisplay = new GroupDisplay(this, group$$1); + this.containerElement.appendChild(groupDisplay.elem); + group$$1.on('changed', () => this.updateDisplay()); + }); + + this.updateDisplay(); + } + + updateDisplay() { + const areAllIdle = groups.reduce( + (prev, next) => prev && next.status === BenchmarkStatus.idle, + true + ); + this.runButton.style.display = areAllIdle ? 'block' : 'none'; + this.stopButton.style.display = areAllIdle ? 'none' : 'block';; + } + + get globalRunOptions() { + return { verifyOnly: this.verifyCheckbox.checked }; + } +} + +/** + * minibench + * https://github.com/SteveSanderson/minibench + */ + +export { HtmlUI }; diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/style.css b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/style.css similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/lib/minibench/style.css rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/style.css diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/renderList.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/renderList.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/BenchmarkEvents.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/BenchmarkEvents.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/BenchmarkEvents.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/BenchmarkEvents.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/BlazorApp.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/BlazorApp.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/BlazorApp.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/BlazorApp.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/DOM.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/DOM.js similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/benchmarks/util/DOM.js rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/util/DOM.js diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/blazor-frame.html b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/blazor-frame.html similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/blazor-frame.html rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/blazor-frame.html diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/index.html b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/index.html similarity index 100% rename from src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/wwwroot/index.html rename to src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/index.html diff --git a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json new file mode 100644 index 000000000000..c2e89394ac05 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json @@ -0,0 +1,15 @@ +{ + "dependencies": [ + "blazorwasmbenchmark" + ], + "services": { + "blazorwasmbenchmark": { + "source": { + "repository": "https://github.com/aspnet/AspNetCore.git", + "branchOrCommit": "prkrishn/blazor-benchmarking", + "dockerfile": "src/Components/benchmarkapps/Wasm.Performance/dockerfile" + }, + "waitForExit": true + } + } +} \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/dockerfile b/src/Components/benchmarkapps/Wasm.Performance/dockerfile new file mode 100644 index 000000000000..126c172b9a81 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/dockerfile @@ -0,0 +1,32 @@ +FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build + +ARG DEBIAN_FRONTEND=noninteractive + +# Setup for nodejs +RUN curl -sL https://deb.nodesource.com/setup_13.x | bash - + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + libunwind-dev \ + nodejs \ + git + +ARG gitBranch=prkrishn/blazor-benchmarking + +WORKDIR /src +ADD https://api.github.com/repos/dotnet/aspnetcore/git/ref/heads/${gitBranch} /aspnetcore.commit + +RUN git init \ + && git fetch https://github.com/aspnet/aspnetcore ${gitBranch} \ + && git reset --hard FETCH_HEAD \ + && git submodule update --init + +RUN dotnet publish -c Release -r linux-x64 -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj +RUN chmod +x /app/Wasm.Performance.Driver + +WORKDIR /app +FROM selenium/standalone-chrome:3.141.59-mercury as final +COPY --from=build ./app ./ +COPY ./exec.sh ./ + +ENTRYPOINT [ "bash", "./exec.sh" ] \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/exec.sh b/src/Components/benchmarkapps/Wasm.Performance/exec.sh new file mode 100644 index 000000000000..bae38ae1e166 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/exec.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +/opt/bin/start-selenium-standalone.sh& +./Wasm.Performance.Driver + diff --git a/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile new file mode 100644 index 000000000000..b5c7578be825 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile @@ -0,0 +1,7 @@ +FROM selenium/standalone-chrome:3.141.59-mercury as final + +WORKDIR /app +COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./ +COPY ./exec.sh ./exec.sh + +ENTRYPOINT [ "bash", "./exec.sh" ] \ No newline at end of file diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj index ac69ac235a90..95b621f8ed90 100644 --- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj +++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj @@ -38,7 +38,7 @@ </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\Blazor\testassets\Microsoft.AspNetCore.Blazor.E2EPerformance\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj" /> + <ProjectReference Include="..\..\benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj" /> <ProjectReference Include="..\..\Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj" /> <ProjectReference Include="..\..\Blazor\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj" /> <ProjectReference Include="..\..\Blazor\testassets\MonoSanityClient\MonoSanityClient.csproj" /> diff --git a/src/Components/test/E2ETest/Tests/PerformanceTest.cs b/src/Components/test/E2ETest/Tests/PerformanceTest.cs index 652226bf26c0..d5cb01b77cd4 100644 --- a/src/Components/test/E2ETest/Tests/PerformanceTest.cs +++ b/src/Components/test/E2ETest/Tests/PerformanceTest.cs @@ -13,11 +13,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests { public class PerformanceTest - : ServerTestBase<DevHostServerFixture<Blazor.E2EPerformance.Program>> + : ServerTestBase<DevHostServerFixture<Wasm.Performance.TestApp.Program>> { public PerformanceTest( BrowserFixture browserFixture, - DevHostServerFixture<Blazor.E2EPerformance.Program> serverFixture, + DevHostServerFixture<Wasm.Performance.TestApp.Program> serverFixture, ITestOutputHelper output) : base(browserFixture, serverFixture, output) { From dd524df6bbf0addee919f9192fa34df8e0547b2b Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Thu, 9 Jan 2020 18:51:21 -0800 Subject: [PATCH 047/322] Application started --- .../Wasm.Performance/Driver/Program.cs | 3 +++ .../Wasm.Performance/benchmarks.compose.json | 25 ++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index 8075d83bddad..99ddc9742053 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -37,6 +37,9 @@ public static async Task<int> Main(string[] args) } } + // This write is required for the benchmarking infrastructure. + Console.WriteLine("Application started."); + using var browser = await Selenium.CreateBrowser(seleniumPort); using var testApp = StartTestApp(); diff --git a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json index c2e89394ac05..9c1aceac9466 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json +++ b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json @@ -1,15 +1,16 @@ { - "dependencies": [ - "blazorwasmbenchmark" - ], - "services": { - "blazorwasmbenchmark": { - "source": { - "repository": "https://github.com/aspnet/AspNetCore.git", - "branchOrCommit": "prkrishn/blazor-benchmarking", - "dockerfile": "src/Components/benchmarkapps/Wasm.Performance/dockerfile" - }, - "waitForExit": true - } + "dependencies": [ + "blazorwasmbenchmark" + ], + "services": { + "blazorwasmbenchmark": { + "source": { + "repository": "https://github.com/dotnet/AspNetCore.git", + "branchOrCommit": "prkrishn/blazor-benchmarking", + "dockerfile": "src/Components/benchmarkapps/Wasm.Performance/dockerfile" + }, + "waitForExit": true, + "readyStateText": "Application started." } + } } \ No newline at end of file From 1e62df1a2da79792092eba5dfa2f3a86a87e3c5e Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Thu, 9 Jan 2020 19:02:28 -0800 Subject: [PATCH 048/322] Try self-contained --- .../Driver/BenchmarkResultsStartup.cs | 6 ++- .../Wasm.Performance/Driver/Program.cs | 39 ++++++++++++++----- .../Wasm.Performance/Driver/Selenium.cs | 30 ++++++++++++-- .../benchmarkapps/Wasm.Performance/README.md | 8 ++-- .../TestApp/wwwroot/benchmarks/index.js | 5 ++- .../benchmarks/lib/minibench/minibench.js | 2 +- .../Wasm.Performance/benchmarks.compose.json | 17 +++++--- .../benchmarkapps/Wasm.Performance/dockerfile | 4 +- .../Wasm.Performance/local.dockerfile | 4 +- .../test/E2ETest/Tests/PerformanceTest.cs | 6 +-- 10 files changed, 85 insertions(+), 36 deletions(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs index 1fa1f067a0d9..7a4af028dfff 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs @@ -5,6 +5,7 @@ using System.Text.Json; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -22,12 +23,13 @@ public void Configure(IApplicationBuilder app) { app.UseCors(); - app.Run(async request => + app.Run(async context => { - var result = await JsonSerializer.DeserializeAsync<List<BenchmarkResult>>(request.Request.Body, new JsonSerializerOptions + var result = await JsonSerializer.DeserializeAsync<List<BenchmarkResult>>(context.Request.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }); + await context.Response.WriteAsync("OK"); Program.SetBenchmarkResult(result); }); } diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index 99ddc9742053..cfaa9cef0fc9 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.ExceptionServices; @@ -40,8 +39,10 @@ public static async Task<int> Main(string[] args) // This write is required for the benchmarking infrastructure. Console.WriteLine("Application started."); - using var browser = await Selenium.CreateBrowser(seleniumPort); + var cancellationToken = new CancellationTokenSource(Timeout); + cancellationToken.Token.Register(() => benchmarkResult.TrySetException(new TimeoutException($"Timed out after {Timeout}"))); + using var browser = await Selenium.CreateBrowser(seleniumPort, cancellationToken.Token); using var testApp = StartTestApp(); using var benchmarkReceiver = StartBenchmarkResultReceiver(); @@ -54,9 +55,6 @@ public static async Task<int> Main(string[] args) browser.Url = launchUrl; browser.Navigate(); - var cancellationToken = new CancellationTokenSource(Timeout); - cancellationToken.Token.Register(() => benchmarkResult.TrySetException(new TimeoutException($"Timed out after {Timeout}"))); - var results = await benchmarkResult.Task; FormatAsBenchmarksOutput(results); @@ -96,24 +94,45 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) output.Metadata.Add(new BenchmarkMetadata { Source = "BlazorWasm", - Name = "Publish size (linked)", - ShortDescription = "Publish size - linked app (MB)", - LongDescription = "Publish size - linked app (MB)", + Name = "Publish size", + ShortDescription = "Publish size (KB)", + LongDescription = "Publish size (KB)", Format = "n2", }); var testAssembly = typeof(TestApp.Startup).Assembly; + var testAssemblyLocation = new FileInfo(testAssembly.Location); var testApp = new DirectoryInfo(Path.Combine( - Path.GetDirectoryName(testAssembly.Location), + testAssemblyLocation.Directory.FullName, testAssembly.GetName().Name)); output.Measurements.Add(new BenchmarkMeasurement { Timestamp = DateTime.UtcNow, - Name = "Publish size (linked)", + Name = "Publish size", Value = GetDirectorySize(testApp) / 1024, }); + output.Metadata.Add(new BenchmarkMetadata + { + Source = "BlazorWasm", + Name = "Publish size (compressed)", + ShortDescription = "Publish size compressed app (KB)", + LongDescription = "Publish size - compressed app (KB)", + Format = "n2", + }); + + var gzip = new FileInfo(Path.Combine( + testAssemblyLocation.Directory.FullName, + $"{testAssembly.GetName().Name}.gzip")); + + output.Measurements.Add(new BenchmarkMeasurement + { + Timestamp = DateTime.UtcNow, + Name = "Publish size (compressed)", + Value = (gzip.Exists ? gzip.Length : 0) / 1024, + }); + Console.WriteLine("#StartJobStatistics"); Console.WriteLine(JsonSerializer.Serialize(output)); Console.WriteLine("#EndJobStatistics"); diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs index 169d3735a12a..1c30e69e20b0 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs @@ -2,8 +2,10 @@ // 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.Net; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; @@ -14,8 +16,9 @@ namespace Wasm.Performance.Driver class Selenium { static bool RunHeadlessBrowser = true; + static bool PoolForBrowserLogs = true; - private static async ValueTask<Uri> WaitForServerAsync(int port) + private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationToken cancellationToken) { var uri = new UriBuilder("http", "localhost", port, "/wd/hub/").Uri; var httpClient = new HttpClient @@ -34,7 +37,7 @@ private static async ValueTask<Uri> WaitForServerAsync(int port) retries++; try { - var response = (await httpClient.GetAsync("status")).EnsureSuccessStatusCode(); + var response = (await httpClient.GetAsync("status", cancellationToken)).EnsureSuccessStatusCode(); Console.WriteLine("Connected to Selenium"); return uri; } @@ -52,9 +55,9 @@ private static async ValueTask<Uri> WaitForServerAsync(int port) throw new Exception($"Unable to connect to selenium-server at {uri}"); } - public static async Task<RemoteWebDriver> CreateBrowser(int port) + public static async Task<RemoteWebDriver> CreateBrowser(int port, CancellationToken cancellationToken) { - var uri = await WaitForServerAsync(port); + var uri = await WaitForServerAsync(port, cancellationToken); var options = new ChromeOptions(); @@ -82,6 +85,25 @@ public static async Task<RemoteWebDriver> CreateBrowser(int port) driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1); + if (PoolForBrowserLogs) + { + // Run in background. + var logs = new RemoteLogs(driver); + _ = Task.Run(async () => + { + while (!cancellationToken.IsCancellationRequested) + { + await Task.Delay(TimeSpan.FromSeconds(3)); + + var consoleLogs = logs.GetLog(LogType.Browser); + foreach (var entry in consoleLogs) + { + Console.WriteLine($"[Browser Log]: {entry.Timestamp}: {entry.Message}"); + } + } + }); + } + return driver; } catch (Exception ex) diff --git a/src/Components/benchmarkapps/Wasm.Performance/README.md b/src/Components/benchmarkapps/Wasm.Performance/README.md index ac0f59e5700a..9522ecc50248 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/README.md +++ b/src/Components/benchmarkapps/Wasm.Performance/README.md @@ -5,7 +5,9 @@ See https://github.com/aspnet/Benchmarks#benchmarks for usage guidance on using ### Running the benchmarks -The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. The Driver is an app that speaks the Benchmark protocol. You generally do not need to run the Driver locally, but if you were to do so, you require docker. Here are the commands you would need to run it locally: +The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. The Driver is an app that connects against an existing Selenium server, and speaks the Benchmark protocol. You generally do not need to run the Driver locally, but if you were to do so, you can either start a selenium-server instance and run using `dotnet run [<selenium-server-port>]` or run it inside a Linux-based docker container. + +Here are the commands you would need to run it locally inside docker: 1. `dotnet publish -c Release -r linux-x64 Driver/Wasm.Performance.Driver.csproj` 2. `docker build -t blazor-local -f ./local.dockerfile . ` @@ -14,5 +16,5 @@ The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. T To run the benchmark app in the Benchmark server, run ``` -dotnet run -- --config aspnetcore/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json --services.blazorwasmbenchmark.endpoints <BenchmarkServerUri> -``` \ No newline at end of file +dotnet run -- --config aspnetcore/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json application.endpoints <BenchmarkServerUri> --scenario blazorwasmbenchmark +``` diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js index 6a1ba57f8222..c1690cfac87d 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/index.js @@ -1,7 +1,7 @@ import { groups, BenchmarkEvent, onBenchmarkEvent } from './lib/minibench/minibench.js'; import { HtmlUI } from './lib/minibench/minibench.ui.js'; -// import './appStartup.js'; -// import './renderList.js'; +import './appStartup.js'; +import './renderList.js'; import './jsonHandling.js'; new HtmlUI('E2E Performance', '#display'); @@ -21,6 +21,7 @@ if (location.href.indexOf('#automated') !== -1) { break; case BenchmarkEvent.benchmarkCompleted: case BenchmarkEvent.benchmarkError: + console.log(`Completed benchmark ${args.name}`); benchmarksResults.push(args); break; case BenchmarkEvent.runCompleted: diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js index 6d13c5657791..241721ceeb13 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js @@ -302,7 +302,7 @@ class Group extends EventEmitter { } const groups = []; -let reportBenchmarkEvent; +let reportBenchmarkEvent = () => {}; function group(name, configure) { groups.push(new Group(name)); diff --git a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json index 9c1aceac9466..81607364dc6f 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json +++ b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json @@ -1,16 +1,21 @@ { - "dependencies": [ - "blazorwasmbenchmark" - ], - "services": { + "$schema": "https://raw.githubusercontent.com/aspnet/Benchmarks/master/src/BenchmarksDriver2/benchmarks.schema.json", + "scenarios": { + "blazorwasmbenchmark": { + "application": { + "job": "blazorwasmbenchmark" + } + } + }, + "jobs": { "blazorwasmbenchmark": { "source": { "repository": "https://github.com/dotnet/AspNetCore.git", - "branchOrCommit": "prkrishn/blazor-benchmarking", + "branchOrCommit": "blazor-wasm", "dockerfile": "src/Components/benchmarkapps/Wasm.Performance/dockerfile" }, "waitForExit": true, "readyStateText": "Application started." } } -} \ No newline at end of file +} diff --git a/src/Components/benchmarkapps/Wasm.Performance/dockerfile b/src/Components/benchmarkapps/Wasm.Performance/dockerfile index 126c172b9a81..69f27a921231 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/dockerfile +++ b/src/Components/benchmarkapps/Wasm.Performance/dockerfile @@ -11,7 +11,7 @@ RUN apt-get update \ nodejs \ git -ARG gitBranch=prkrishn/blazor-benchmarking +ARG gitBranch=blazor-wasm WORKDIR /src ADD https://api.github.com/repos/dotnet/aspnetcore/git/ref/heads/${gitBranch} /aspnetcore.commit @@ -29,4 +29,4 @@ FROM selenium/standalone-chrome:3.141.59-mercury as final COPY --from=build ./app ./ COPY ./exec.sh ./ -ENTRYPOINT [ "bash", "./exec.sh" ] \ No newline at end of file +ENTRYPOINT [ "bash", "./exec.sh" ] diff --git a/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile index b5c7578be825..188bc5dc5a81 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile +++ b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile @@ -2,6 +2,6 @@ FROM selenium/standalone-chrome:3.141.59-mercury as final WORKDIR /app COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./ -COPY ./exec.sh ./exec.sh +COPY ./exec.sh ./ -ENTRYPOINT [ "bash", "./exec.sh" ] \ No newline at end of file +ENTRYPOINT [ "bash", "./exec.sh" ] diff --git a/src/Components/test/E2ETest/Tests/PerformanceTest.cs b/src/Components/test/E2ETest/Tests/PerformanceTest.cs index d5cb01b77cd4..f7187a45573e 100644 --- a/src/Components/test/E2ETest/Tests/PerformanceTest.cs +++ b/src/Components/test/E2ETest/Tests/PerformanceTest.cs @@ -52,10 +52,8 @@ public void BenchmarksRunWithoutError() () => runAllButton.Displayed || Browser.FindElements(By.CssSelector(".benchmark-error")).Any(), TimeSpan.FromSeconds(60)); - var finishedBenchmarks = Browser.FindElements(By.CssSelector(".benchmark-idle")); - var failedBenchmarks = Browser.FindElements(By.CssSelector(".benchmark-error")); - Assert.NotEmpty(finishedBenchmarks); - Assert.Empty(failedBenchmarks); + Browser.DoesNotExist(By.CssSelector(".benchmark-error")); // no failures + Browser.Exists(By.CssSelector(".benchmark-idle")); // everything's done } } } From e64b8a91ad1a5acea64f7d2a51ac00618ad96876 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson <jacalvar@microsoft.com> Date: Fri, 17 Jan 2020 12:44:30 -0800 Subject: [PATCH 049/322] [Fixes #17014] Add an auth-enabled template for Blazor WASM projects (#18354) * [Fixes #17014] Add an auth-enabled template for Blazor WASM projects * The template enables auth using cookies. * Includes a UserController to return the user claims/data to the user * Includes an IdentityAuthenticationStateProvider that fetches the claims data from the application. * It requires a hosted project. --- eng/Versions.props | 4 + .../BlazorWasm-CSharp.Client.csproj.in | 1 + .../BlazorWasm-CSharp.Server.csproj.in | 17 ++ ...crosoft.AspNetCore.Blazor.Templates.csproj | 10 +- .../.template.config/dotnetcli.host.json | 28 +- .../.template.config/template.json | 181 ++++++++++++ .../.template.config/vs-2017.3.host.json | 24 ++ .../BlazorWasm-CSharp/Client/App.razor | 17 +- .../Client/Pages/FetchData.razor | 6 + .../HostAuthenticationStateProvider.cs | 56 ++++ .../LoginDisplay.IndividualLocalAuth.razor | 12 + .../Client/Shared/MainLayout.Auth.razor | 16 + ...inLayout.razor => MainLayout.NoAuth.razor} | 0 .../BlazorWasm-CSharp/Client/Startup.cs | 7 + .../BlazorWasm-CSharp/Client/_Imports.razor | 3 + .../Client/wwwroot/favicon.ico | Bin 0 -> 32038 bytes .../Identity/Pages/Account/LogOut.cshtml | 15 + .../Pages/Shared/_LoginPartial.cshtml | 27 ++ .../Server/Controllers/UserController.cs | 61 ++++ .../Controllers/WeatherForecastController.cs | 6 + .../Server/Data/ApplicationDbContext.cs | 16 + ...000000000_CreateIdentitySchema.Designer.cs | 270 +++++++++++++++++ .../00000000000000_CreateIdentitySchema.cs | 217 ++++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 268 +++++++++++++++++ ...000000000_CreateIdentitySchema.Designer.cs | 277 ++++++++++++++++++ .../00000000000000_CreateIdentitySchema.cs | 220 ++++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 275 +++++++++++++++++ .../BlazorWasm-CSharp/Server/Startup.cs | 61 +++- .../content/BlazorWasm-CSharp/Server/app.db | Bin 0 -> 106496 bytes .../Server/appsettings.Development.json | 9 + .../BlazorWasm-CSharp/Server/appsettings.json | 19 ++ .../Shared/Authorization/ClaimValue.cs | 18 ++ .../Shared/Authorization/UserInfo.cs | 19 ++ .../test/BlazorWasmTemplateTest.cs | 107 ++++++- 34 files changed, 2256 insertions(+), 11 deletions(-) create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor rename src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/{MainLayout.razor => MainLayout.NoAuth.razor} (100%) create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs diff --git a/eng/Versions.props b/eng/Versions.props index d2e01e6ef5a0..e1dab327ee4f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -204,6 +204,10 @@ <SystemThreadingTasksExtensionsPackageVersion>4.5.2</SystemThreadingTasksExtensionsPackageVersion> <!-- Packages developed by @aspnet, but manually updated as necessary. --> <LibuvPackageVersion>1.10.0</LibuvPackageVersion> + <MicrosoftAspNetCoreIdentityUIPackageVersion>3.1.0</MicrosoftAspNetCoreIdentityUIPackageVersion> + <MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>3.1.0</MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion> + <MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>3.1.0</MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion> + <MicrosoftAspNetCoreComponentsAuthorizationPackageVersion>3.1.0</MicrosoftAspNetCoreComponentsAuthorizationPackageVersion> <MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion> <!-- Partner teams --> <MicrosoftAzureKeyVaultPackageVersion>2.3.2</MicrosoftAzureKeyVaultPackageVersion> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in index 70927b08e331..3ef13b2f3344 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in @@ -10,6 +10,7 @@ <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="${MicrosoftAspNetCoreBlazorBuildPackageVersion}" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="${MicrosoftAspNetCoreBlazorDevServerPackageVersion}" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="${MicrosoftAspNetCoreBlazorHttpClientPackageVersion}" /> + <PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="${MicrosoftAspNetCoreComponentsAuthorizationPackageVersion}" Condition="'$(IndividualLocalAuth)' == 'true'" /> </ItemGroup> <!--#if Hosted --> <ItemGroup> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in index 5fe7473679dc..dd9965626c1f 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in @@ -13,4 +13,21 @@ <ProjectReference Include="..\Shared\BlazorWasm-CSharp.Shared.csproj" /> </ItemGroup> + <!--#if (IndividualLocalAuth && !UseLocalDB) --> + <ItemGroup> + <None Update="app.db" CopyToOutputDirectory="PreserveNewest" ExcludeFromSingleFile="true" /> + </ItemGroup> + + <!--#endif --> + <!--#if (IndividualLocalAuth) --> + <ItemGroup> + <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="${MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion}" /> + <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="${MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion}" /> + <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="${MicrosoftAspNetCoreIdentityUIPackageVersion}" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="${MicrosoftEntityFrameworkCoreSqlServerPackageVersion}" Condition="'$(UseLocalDB)' == 'True'" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="${MicrosoftEntityFrameworkCoreSqlitePackageVersion}" Condition="'$(UseLocalDB)' != 'True'" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="${MicrosoftEntityFrameworkCoreToolsPackageVersion}" /> + </ItemGroup> + + <!--#endif --> </Project> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj index 65457a000d35..5ae2bfe6cac2 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj @@ -20,9 +20,15 @@ MicrosoftAspNetCoreBlazorBuildPackageVersion=$(MicrosoftAspNetCoreBlazorBuildPackageVersion); MicrosoftAspNetCoreBlazorDevServerPackageVersion=$(MicrosoftAspNetCoreBlazorDevServerPackageVersion); MicrosoftAspNetCoreBlazorHttpClientPackageVersion=$(MicrosoftAspNetCoreBlazorHttpClientPackageVersion); - MonoWebAssemblyInteropPackageVersion=$(MonoWebAssemblyInteropPackageVersion); - MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion); + MicrosoftAspNetCoreComponentsAuthorizationPackageVersion=$(MicrosoftAspNetCoreComponentsAuthorizationPackageVersion); + MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion=$(MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion); + MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion=$(MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion); + MicrosoftAspNetCoreIdentityUIPackageVersion=$(MicrosoftAspNetCoreIdentityUIPackageVersion); + MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); + MicrosoftEntityFrameworkCoreSqlitePackageVersion=$(MicrosoftEntityFrameworkCoreSqlitePackageVersion); + MicrosoftEntityFrameworkCoreToolsPackageVersion=$(MicrosoftEntityFrameworkCoreToolsPackageVersion); + MonoWebAssemblyInteropPackageVersion=$(MonoWebAssemblyInteropPackageVersion); </GeneratedContentProperties> </PropertyGroup> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json index 4e89e1d2dca8..38651820f211 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json @@ -5,11 +5,31 @@ "longName": "no-restore", "shortName": "" }, - "Hosted": { - "longName": "hosted" - }, + "Hosted": { + "longName": "hosted" + }, "Framework": { "longName": "framework" + }, + "UseLocalDB": { + "longName": "use-local-db" + }, + "HttpPort": { + "isHidden": true + }, + "HttpsPort": { + "isHidden": true + }, + "ExcludeLaunchSettings": { + "longName": "exclude-launch-settings", + "shortName": "" + }, + "UserSecretsId": { + "isHidden": true + }, + "NoHttps": { + "longName": "no-https", + "shortName": "" } } -} \ No newline at end of file +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json index b6cb64fcec5f..d2e1735f7e66 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json @@ -74,6 +74,82 @@ "exclude": [ "*.sln" ] + }, + { + "condition": "(!IndividualLocalAuth || UseLocalDB)", + "exclude": [ + "Server/app.db" + ] + }, + { + "condition": "(!IndividualLocalAuth)", + "exclude": [ + "Server/Data/SqlLite/**", + "Server/Data/SqlServer/**", + "Server/Data/ApplicationDbContext.cs", + "Server/Areas/**" + ] + }, + { + "condition": "(IndividualLocalAuth && UseLocalDB)", + "rename": { + "Server/Data/SqlServer/": "Server/Data/Migrations/" + }, + "exclude": [ + "Server/Data/SqlLite/**" + ] + }, + { + "condition": "(IndividualLocalAuth && !UseLocalDB)", + "rename": { + "Server/Data/SqlLite/": "Server/Data/Migrations/" + }, + "exclude": [ + "Server/Data/SqlServer/**" + ] + }, + { + "condition": "(NoAuth && Hosted)", + "rename": { + "Client/Shared/MainLayout.NoAuth.razor": "Client/Shared/MainLayout.razor" + }, + "exclude": [ + "Client/Shared/LoginDisplay.*.razor", + "Client/Shared/MainLayout.Auth.razor" + ] + }, + { + "condition": "(!Hosted)", + "rename": { + "Client/Shared/MainLayout.NoAuth.razor": "Shared/MainLayout.razor" + }, + "exclude": [ + "Client/Shared/LoginDisplay.*.razor", + "Client/Shared/MainLayout.Auth.razor" + ] + }, + { + "condition": "(!NoAuth && Hosted)", + "rename": { + "Client/Shared/MainLayout.Auth.razor": "Client/Shared/MainLayout.razor" + }, + "exclude": [ + "Client/Shared/MainLayout.NoAuth.razor" + ] + }, + { + "condition": "(IndividualLocalAuth)", + "rename": { + "Client/Shared/LoginDisplay.IndividualLocalAuth.razor": "Client/Shared/LoginDisplay.razor" + } + }, + { + "condition": "(NoAuth)", + "exclude": [ + "Client/Services/HostAuthenticationStateProvider.cs", + "Server/Controllers/UserController.cs", + "Shared/Authorization/*" + ] } ] } @@ -107,6 +183,111 @@ "datatype": "bool", "defaultValue": "false", "description": "If specified, includes an ASP.NET Core host for the Blazor app." + }, + "auth": { + "type": "parameter", + "datatype": "choice", + "choices": [ + { + "choice": "None", + "description": "No authentication" + }, + { + "choice": "Individual", + "description": "Individual authentication" + } + ], + "defaultValue": "None", + "description": "The type of authentication to use" + }, + "UserSecretsId": { + "type": "parameter", + "datatype": "string", + "replaces": "aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502", + "defaultValue": "aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502", + "description": "The ID to use for secrets (use with OrgReadAccess or Individual auth)." + }, + "ExcludeLaunchSettings": { + "type": "parameter", + "datatype": "bool", + "defaultValue": "false", + "description": "Whether to exclude launchSettings.json from the generated template." + }, + "HttpPort": { + "type": "parameter", + "datatype": "integer", + "description": "Port number to use for the HTTP endpoint in launchSettings.json." + }, + "HttpPortGenerated": { + "type": "generated", + "generator": "port" + }, + "HttpPortReplacer": { + "type": "generated", + "generator": "coalesce", + "parameters": { + "sourceVariableName": "HttpPort", + "fallbackVariableName": "HttpPortGenerated" + }, + "replaces": "8080" + }, + "HttpsPort": { + "type": "parameter", + "datatype": "integer", + "description": "Port number to use for the HTTPS endpoint in launchSettings.json. This option is only applicable when the parameter no-https is not used (no-https will be ignored if either IndividualAuth or OrganizationalAuth is used)." + }, + "HttpsPortGenerated": { + "type": "generated", + "generator": "port", + "parameters": { + "low": 44300, + "high": 44399 + } + }, + "HttpsPortReplacer": { + "type": "generated", + "generator": "coalesce", + "parameters": { + "sourceVariableName": "HttpsPort", + "fallbackVariableName": "HttpsPortGenerated" + }, + "replaces": "44300" + }, + "IndividualLocalAuth": { + "type": "computed", + "value": "(auth == \"Individual\")" + }, + "NoAuth": { + "type": "computed", + "value": "(!(IndividualAuth))" + }, + "IndividualAuth": { + "type": "computed", + "value": "(IndividualLocalAuth)" + }, + "RequiresHttps": { + "type": "computed", + "value": "(IndividualAuth || !NoHttps)" + }, + "NoHttps": { + "type": "parameter", + "datatype": "bool", + "defaultValue": "false", + "description": "Whether to turn off HTTPS. This option only applies if Individual, IndividualB2C, SingleOrg, or MultiOrg aren't used for --auth." + }, + "UseLocalDB": { + "type": "parameter", + "datatype": "bool", + "defaultValue": "false", + "description": "Whether to use LocalDB instead of SQLite. This option only applies if --auth Individual or --auth IndividualB2C is specified." + }, + "copyrightYear": { + "type": "generated", + "generator": "now", + "replaces": "copyrightYear", + "parameters": { + "format": "yyyy" + } } }, "tags": { diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json index 5cb50d10a519..cbed84838b4e 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json @@ -18,6 +18,30 @@ "additionalWizardParameters": { "$isMultiProjectTemplate$": "true" }, + "supportedAuthentications": [ + { + "auth": "None", + "authenticationType": "NoAuth", + "allowUnsecured": true + }, + { + "auth": "Individual", + "authenticationType": "IndividualAuth", + "b2cAuthenticationOptions": "Local" + } + ], + "ports": [ + { + "name": "HttpPort", + "useHttps": false + }, + { + "name": "HttpsPort", + "useHttps": true + } + ], + "excludeLaunchSettings": false, + "disableHttpsSymbol": "NoHttps", "symbolInfo": [ { "id": "Hosted", diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor index 1c360b7121a7..7b58ea096f72 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor @@ -1,4 +1,5 @@ -<Router AppAssembly="@typeof(Program).Assembly"> +@*#if (NoAuth) +<Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> @@ -8,3 +9,17 @@ </LayoutView> </NotFound> </Router> +#else +<CascadingAuthenticationState> + <Router AppAssembly="@typeof(Program).Assembly"> + <Found Context="routeData"> + <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> + </Found> + <NotFound> + <LayoutView Layout="@typeof(MainLayout)"> + <p>Sorry, there's nothing at this address.</p> + </LayoutView> + </NotFound> + </Router> +</CascadingAuthenticationState> +#endif*@ diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor index 0faf18fefd34..99cda40a53b0 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor @@ -1,7 +1,13 @@ @page "/fetchdata" +@*#if (!NoAuth) +@using Microsoft.AspNetCore.Authorization +#endif*@ @*#if (Hosted) @using BlazorWasm_CSharp.Shared #endif*@ +@*#if (!NoAuth) +@attribute [Authorize] +#endif*@ @inject HttpClient Http <h1>Weather forecast</h1> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs new file mode 100644 index 000000000000..efb2cd636d9d --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs @@ -0,0 +1,56 @@ +using BlazorWasm_CSharp.Shared.Authorization; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace BlazorWasm_CSharp.Client +{ + public class HostAuthenticationStateProvider : AuthenticationStateProvider + { + private readonly HttpClient _client; + private ClaimsPrincipal _currentUser; + + public HostAuthenticationStateProvider(HttpClient client) + { + _client = client; + } + + public override async Task<AuthenticationState> GetAuthenticationStateAsync() + { + if (_currentUser == null) + { + await FetchUser(); + } + + return new AuthenticationState(_currentUser); + } + + private async Task FetchUser() + { + var user = await _client.GetJsonAsync<UserInfo>("User"); + + if (!user.IsAuthenticated) + { + _currentUser = new ClaimsPrincipal(new ClaimsIdentity()); + return; + } + + var identity = new ClaimsIdentity( + nameof(HostAuthenticationStateProvider), + user.NameClaimType, + user.RoleClaimType); + + if (user.Claims != null) + { + foreach (var claim in user.Claims) + { + identity.AddClaim(new Claim(claim.Type, claim.Value)); + } + } + + _currentUser = new ClaimsPrincipal(identity); + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor new file mode 100644 index 000000000000..25f9db264b4a --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor @@ -0,0 +1,12 @@ +<AuthorizeView> + <Authorized> + <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a> + <form method="post" action="Identity/Account/LogOut"> + <button type="submit" class="nav-link btn btn-link">Log out</button> + </form> + </Authorized> + <NotAuthorized> + <a href="Identity/Account/Register">Register</a> + <a href="Identity/Account/Login">Log in</a> + </NotAuthorized> +</AuthorizeView> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor new file mode 100644 index 000000000000..fafa2f55f105 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor @@ -0,0 +1,16 @@ +@inherits LayoutComponentBase + +<div class="sidebar"> + <NavMenu /> +</div> + +<div class="main"> + <div class="top-row px-4 auth"> + <LoginDisplay /> + <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> + </div> + + <div class="content px-4"> + @Body + </div> +</div> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.NoAuth.razor similarity index 100% rename from src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.NoAuth.razor diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs index b30f14ae0609..38fd10a30eac 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs @@ -1,3 +1,6 @@ +#if (!NoAuth) +using Microsoft.AspNetCore.Components.Authorization; +#endif using Microsoft.AspNetCore.Components.Builder; using Microsoft.Extensions.DependencyInjection; @@ -11,6 +14,10 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { +#if (IndividualLocalAuth) + services.AddAuthorizationCore(); + services.AddSingleton<AuthenticationStateProvider, HostAuthenticationStateProvider>(); +#endif } public void Configure(IComponentsApplicationBuilder app) diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor index 912a5070c2f4..fa501010b9f6 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor @@ -1,4 +1,7 @@ @using System.Net.Http +@*#if (!NoAuth) +@using Microsoft.AspNetCore.Components.Authorization +#endif*@ @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a3a799985c43bc7309d701b2cad129023377dc71 GIT binary patch literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85<eW@6XRp%jD>=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$Q<HOixSl<aTM__jl4#^thzg zR%8kDj}7!lG~6zIy}i=c(}UmYmfr3z>Fr9nP<Q2WYG!6yx=!tqj{N(it>g(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP<k8>8W}_qJ<Ai`=Ou7 z`ue&ogWfUli9DMc8&O<H4|y`$*Ck6>L$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}<eeQ3J;Ww5b2VCRhCywj)`%eE_;>C|iN7)YN`^)<MX{;gTi@1yp^{2@b;(+g` zAt&imr^?OutN&RNC7A!n)B63jwKbWao5ecJ%hKY!EZ~|jkF}#Ltw6^3x5~;&{eFM- zi;^sTLgE!Ky7P}i#{58fMnFeDcsGT0=<Dl~`uh4mC;g*M#nOM~MM+)Qlk@xhE}^NZ zQ9_}Rw6?bH#)oeiA0L;6g#`s(=X#N*<>h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F<Rt1N8OKCQyfy(wj_3Pa+10N>3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4<M8Hm<td$i zo%63^{uMj_JZyl2H|=@`4jvvW(-Ts0+?#)(Zm%@H_UF>{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{<Wz0W0IwJGaQ;Ngf)HrbH_i%t+ zRbG%E4pf{tRz1*<`LTY34f{a*UrA^`{Keb<8-DNe(tP~azWFT<h7USFe1h^|)$m|) zY*glF%>484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKn<s0*3P3iB*gT^a0vIzTZU|trn2Uv9c3Hh)9f3g4{&h?nbULpvN z96n^`Pp`^wOQE#w`Lc8replMCXK8)sOVV=kx5^vt9Vp{-(Alv;%nuxzF#i;MKYb4U zzQV*feDk<Wj*l6DJWwXMCX~$yAMpLrvcuJb0|Uy(;g%w4-TgPxaq!#HhPhjz2Q4Rm zgZUv_3Y>o;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?<y`V ztR5U35HLVSIse|TN~8$;o%g;jAzZhXzwF3Z8snPGVLi>B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskka<HNc) zw7%ikv18A{=YN3n^EKXnL?Q>iCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE<WT-@UlL8}x(!oZA8J5zU^H z^A9LLlqc{rSK**`!q^J#O?mF{`>*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YB<mKXAV!4?lsqzpK~nm2X@% zznz;rn1?^*{QmQRy*7FZTn2bH>Xz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FE<n#M zl!>e}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5a<V_m; zgjM+PrKKg|+4S7GbD8ri{bv3|(WAftcJSQ3j463m3!*jX9@l3SwsIJ9$n(_<d<V}- zdM?8m`TY6woc|B3{h0`#lz73zk}Uaq<w4i6rzBQ)?7HUX-1c18+m(<moCSvAXLye5 zh5c`8YLaL)x*b1$i#PuXiRV8kiNc2^j&+D1gdfb}|5oTH&30~%=gw3MWL>JOtL4<G zQ+geX#i}{CfBuEhxKIYkhY836$5h(|e8hWgX@2-7&O3^caOQNC+RsJA9=Z|lz!|j~ zzv!M%E&bjs-ql8b^FEb%#q+R*m6a8_c=4j1p}V@eu9_R)yao8k1Y%7=kV>U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09<pd zBG-35{NWG(mj@qs;K5x_@BH1ar=NZmqYF>(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<<HU zYqNw~nxvi3+#u~u4m8wBdt;r18fqQ5f-wkc<;fra!=7j)qI)jCZL`;m=MLi>t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32Z<i}p+w67N1l-O`bz9E2Q&Prl{J&c zFtWxN6yt(CUz#|WFBayHKRA5RSe_Guv1?%CbBu>AE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh<puUpgSc4h;a^JPcx88NIwB_wZ3>1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h<Y-#lOkKs1PG-dHahJ zM$9B!@NH=agbTkTEj7nH{j+*#V~1D+#UC`_oFZ}Me`Xv{@kczB_^%*-rLiN#^HvZC zW(<sHDV`^1p=WbA*Ya%3^OlV(W{)pCXZUY^cUfk7fj?qhj5jjg$(WPI9Nz{#c;9@! z)Zp*vi`o)@{L|5U;-82?ew;X@(E~@0um(f0$%}}ESvgw3SzYA_xsriy$PoeZL|V8W z{@A2<JtHqX_pFg0#+X+jKYhgiuT=-g|90fanqL15WCybU=I0>)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE<xtH<PVcLDjlozY_*>0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E<eJzSD0o_jT(!I%bYf7s+A4F4S&vU&{u zGbX8LWQ`N}<B$_Fk65OWB{ME!ZERdNV}zY};koB_$6`_N2)YHB>2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudx<WJi9vaTgF5Z9j)pgxL;;`&B{@bE%JPV^=rl!1jcq@Z#B+K zI|2CR^UoXk0q$!Sf5ta~Z|k1Fh3?+3@pjdRw-9@${9~P5058{|`@~;!oxq)E`a}o( z8TJsw+Xa=SEL)22TOOnx8*XCLjxTj%)P9=0>tDVA{K5Y<t}S3@pcVZ8Th-w<@*n!! z{5Iw1^Pc<=f6hypBmP*AsZr+1oqVnGKO_xxS8yg@lnLzHXK^lHLXLT2Y)od6$6zjW z9C6|q#F-b7CmbIcmKp4m7BvnvBs0jtGR{3Vggi9%Ow@12rlw(+%(c0Xy{wTRCzd-q z*e0R(?n0dVtJ1#zZi$pWqOotrym_zr!eLj|ROWD&A`Mex27eRR=>h*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u<d{7CivIL!OYgVGO<b{2`UIHP{i#n~qoq@_&@^AO(Z} z#dBx%d`SP8OeFNo#JyrN5tr_+l*A&Pl8ncsJC&4ZX9w(URJxP6hTSsP33H9_bi)@% zu_vKVG}rhHu7CFAlP>;@qs|V75Z^|Q0l0?teobTE8t<n*L#~=H98x(W?vyu^e<1&d zVCNt|KKw6VydWvylS1AzNdOH7;z|Q?cL6+10ul;Q-^lCSu>Gl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl<XIQZKGrvIGxelxgp{*E!yiZR}IrSkt->^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7<SN=BJIqx?5B)&%HI%7#(A9E*{D)1a zzF<__h-;n;xMv$>y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;o<tE{OE(?2=<A4MF}#OA>NNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ<hbA{CN2H;rvl^?u=Z#a9)8m2_BTo>56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK<z1EteZqA7EX64Ap4|63J zj4Um~{}W6Oi8&OL<FvV6o6oW%_Z}v%WpZ1@U(esz>-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+&<jfTRckhNg0e{@1{I9PYT{krFIt@FQ zg+FwG^sp{Y@uzMp4aUaWbr@wX&jIfL%sQAoAlG7w_&aAJ|2mvGb0(1gMt;7hdCnN> z>$*<vlz7PxQ0w-nB#-=5Lba8aRA*erxDLBLmXZInYq6sEvo_D#CSM*dTb3*>Hf}}y zkt@nLXFG9%v**s{z&{H4e?aq<G31K6PCl)5elgO3{9)UrlZrQaZ(c^0v}TWI7z^P2 zsLTIFwM(SQ+9#ebDO2=!Tnny)T?^fZ19!?2&qc&PopnY%cm7<U{45MZe<3%K{ohhL zm~)LF=iB)n^a1x;FCKO9wu8Z+e$vIAGyqou>p%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?<hi6;nFqt>!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w<CJ?O>;*RFm;XPDQwx%~;8i<oa^ zexLQs#C;Swe&jxL;2)Pn5quSD44CilIrSXYU_0#4b{VXBL&8lp8{)5e>BzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+t<Pf&d|V}H3F<zNPq^dnLw>P zX$aL;*^g$7<Ue(mJhn9?_FDN)+hp<2y0&!%%(W5co>UyM2Go+_4A+f)IQcy^G$h2E zb?nT$<GLCMXx=#+f8x!0hdAV2X~A_&-#?U7{;x-VC^O92Wb?eSzE+S6RX|=;&pC$< z9g@=0Qq9>XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&l<K=Dpmb{^4-!94u`ca zdNVoO>fae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)J<Y zxc^5t3qJV45B`taZ@>MCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAV<aixb6h<Sg0H6jw4qU zV~?Bz5!)*lmM-iqJqY1C7nsj&+qP{N{V-~a1^op#4Sw~jUm=fL>q0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`<T9_no>l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{<Jh_kyRt}|;t96pc-^Er3` zo}iC2gMPObPU{|m=x2|p6X&-wXJt%zkSPP3@xa!}dGs%8Jc%(S1BMS)CX6g%9UNV- z>v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKo<R02YmTL zqhr<%m_BFM7Fa&y947^SQ}y4{ZAaF|G`@C+sh521)5?cN^cOe0_9@gH-Y$)(pJd(P z_1X@lpSgXfMnLNXGU%rcETRu24v0w?{GLKAA}IoVUkW|qDfm7YI>X3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF<O6FlgJ{<Kj?Q@Wliwb+>?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*S<!No<o1d3X^w>tr(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-<?wRtMA$a{Uv^+e}~R^M`&pP`_w=4t2sW50+lDC-HjPUHYxxaYn6a!kV+c zpX(pPb74a0@ugg}?EV6381FQ7Pgs9Tw;k1Ys~vUZ0Q%wWr;HEDO@F2gSo*u52fF@{ z0q%z~Y=K`6U=z3xA^l!GtVgeR&-iJVe)8J~tTk;$y|}FzXPtY??k~a~!Uo`(3(c&V z#ovwmXW9;9NBlZr@{{g90y1FeXN>^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqz<CJIAM$L1BM%w-GTk@RUOM3L%cGxlX&$hqjP-p4?g8S* zf2wthE%1v3ttI8(g6O9&p&r4WTH3u4^(Uy`C@Z$~Z!QCFO|beXXOCj#AWIfZKZ&zf zwlZ<mX#YOv`9G~&1pUsa&k{hbqt<3(t(AT}<AbzwZ(!($j*x!R8U(=C*57b6bs&@n z(qG`LzmNXS_5(h-GP;nxKcZc<fIT|*=|N!k@%Sua0Na&@Ec*Fei5AudgZ5_Zb=dRL zy5~!dP56w~t?J)Mzt3*i+F{ENmwwIvn;HPhLRoR4kA5Ey0`~*<Tu44!-QpM^3mNiY zd69ec=!ec>FJ?h&Dk<xHrU>@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK<T$Q z`bO#l_@MP@_8AMlIwG!r58^)LK@V~`<U<c)KlBAULJoQm1LD58CzVp$)XfpU%erPW z8sA`jr0x}Uuf#ng_s;N@pg(vtd+S{Ehw)4s))#8cIdmaez5{i`_h`*|+aA>1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8<r-Iaf>U4i~PI>7a3{kVa8<kbN6eyGEHKpnx06E+}DNbur?yk^WW2oOhPEHMzw z=X22?2K^zfKk0w-3x<B|f7Kqq?vehsJ&ym&vK>|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{<?)|7`m4UeEKeU77W{UX5;9iATSc1JZBhfY1KP&`I@+zH<_On{%uq zN9diKefHP4moxi1V~=fpz8!PYj~a2-Rue*yfn@o1>3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpN<VbL&~J6p@r$}YA`b%i;P8Su%#HYA>E=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye<Hud7yLjT^qdxgMfvTOvezVxCTF3Oif0G_WIV`7|<P~nWc ze(AR_33^2C!`bid4}IuE|D80@5BovapS?PO_T6`4{db`M<z8uj=gZLlJGJM6&pb2V z_4I~1<lonN^!s_xCx=V%oYNfrBiZ*!d-lDc_piSEqKx(?Wdva3^UN8rzr^2Ta=Q97 zbMnl0{t<JZx`tWn&mJE>+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB<q)&YlUNAEf(Uu_DAf!GkDzUD%_;=Nj{#_Uqt1dtf5y z;SZ7>(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZ<YY5zOXFUQ`X@ZP(W z{s{U%j85F8y<6<33tE5Ak68a_c;MC|yL{ktG|gVY^ADbn^!84m*MEMxiVt3lk+CKA zNb%h3<?@Xjs4RdF=h6F?ZU20tua_~bKYP8{-xA*Y4e7!9EB(0Udp_^a`hUOO;5Gl# z5jHhr?F00{?z@eCP$vBJ+iSab%;E!Oz$Xi%DibEYrm<#?yF0OWCss@zphsqN`q5Lu zz8>v)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=K<Q;83+yZ2l>S2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaP<Ja6qEsn*3Id6d4Rqr z^l|y<AEzB~*WX9~0M>tHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hz<pvTgWaXk$=0q8wlZ_?`kYW{7!0CX>d{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(<m44z)dfXB6&vU2slR>oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v<nWs((bE+M|w5L=Us_;lY2i^s{%yg6)%J4-lXC#CZGW^gpJ(s_ajV?!O=O z|C7?MHi32l&s(N{*pmI<M2@dV_Wj@S_qE!d#UR?*C(6D*_Cak*KlNXGMIrBy1N}FN z@XUh*`bF7$*>&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2<b;m*$JK^VtIU_Y$NB`p^DNyaH+G z{mp3Lmvg;t<h!|kGyA^37d!i!w9>{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_<!%{oZJ8a literal 0 HcmV?d00001 diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml new file mode 100644 index 000000000000..21b7fe273450 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml @@ -0,0 +1,15 @@ +@page +@using Microsoft.AspNetCore.Identity +@attribute [IgnoreAntiforgeryToken] +@inject SignInManager<IdentityUser> SignInManager +@functions { + public async Task<IActionResult> OnPost() + { + if (SignInManager.IsSignedIn(User)) + { + await SignInManager.SignOutAsync(); + } + + return Redirect("~/"); + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml new file mode 100644 index 000000000000..a4f854aac31f --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml @@ -0,0 +1,27 @@ +@using Microsoft.AspNetCore.Identity +@inject SignInManager<IdentityUser> SignInManager +@inject UserManager<IdentityUser> UserManager +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + +<ul class="navbar-nav"> +@if (SignInManager.IsSignedIn(User)) +{ + <li class="nav-item"> + <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a> + </li> + <li class="nav-item"> + <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="/" method="post"> + <button type="submit" class="nav-link btn btn-link text-dark">Logout</button> + </form> + </li> +} +else +{ + <li class="nav-item"> + <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a> + </li> + <li class="nav-item"> + <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a> + </li> +} +</ul> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs new file mode 100644 index 000000000000..6c27a4ad7c4f --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using BlazorWasm_CSharp.Shared.Authorization; + +namespace BlazorWasm_CSharp.Server.Controllers +{ + [ApiController] + public class UserController : ControllerBase + { + [HttpGet("/User")] + [Authorize] + [AllowAnonymous] + public IActionResult GetCurrentUser() => + Ok(User.Identity.IsAuthenticated ? CreateUserInfo(User) : UserInfo.Anonymous); + + private UserInfo CreateUserInfo(ClaimsPrincipal claimsPrincipal) + { + if (!claimsPrincipal.Identity.IsAuthenticated) + { + return UserInfo.Anonymous; + } + + var userInfo = new UserInfo(); + userInfo.IsAuthenticated = true; + + if (claimsPrincipal.Identity is ClaimsIdentity claimsIdentity) + { + userInfo.NameClaimType = claimsIdentity.NameClaimType; + userInfo.RoleClaimType = claimsIdentity.RoleClaimType; + } + else + { + userInfo.NameClaimType = "name"; + userInfo.RoleClaimType = "roles"; + } + + if (claimsPrincipal.Claims.Any()) + { + var claims = new List<ClaimValue>(); + var nameClaims = claimsPrincipal.FindAll(userInfo.NameClaimType); + foreach (var claim in nameClaims) + { + claims.Add(new ClaimValue(userInfo.NameClaimType, claim.Value)); + } + + // Uncomment this code if you want to send additional claims to the client. + //foreach (var claim in claimsPrincipal.Claims.Except(nameClaims)) + //{ + // claims.Add(new ClaimValue(claim.Type, claim.Value)); + //} + + userInfo.Claims = claims; + } + + return userInfo; + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs index 6862c16a71b3..c6f2eb0ecebe 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs @@ -3,11 +3,17 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +#if (!NoAuth) +using Microsoft.AspNetCore.Authorization; +#endif using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace BlazorWasm_CSharp.Server.Controllers { +#if (!NoAuth) + [Authorize] +#endif [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs new file mode 100644 index 000000000000..81390814c564 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + +namespace BlazorWasm_CSharp.Server.Data +{ + public class ApplicationDbContext : IdentityDbContext + { + public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) + : base(options) + { + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 000000000000..7bea3b5b34bc --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,270 @@ +// <auto-generated /> +using System; +using BlazorWasm_CSharp.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("00000000000000_CreateIdentitySchema")] + partial class CreateIdentitySchema + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("PasswordHash") + .HasColumnType("TEXT"); + + b.Property<string>("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property<string>("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property<string>("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("ProviderKey") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("Name") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 000000000000..1df0c12752ef --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs @@ -0,0 +1,217 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + public partial class CreateIdentitySchema : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column<string>(nullable: false), + Name = table.Column<string>(maxLength: 256, nullable: true), + NormalizedName = table.Column<string>(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column<string>(nullable: false), + UserName = table.Column<string>(maxLength: 256, nullable: true), + NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true), + Email = table.Column<string>(maxLength: 256, nullable: true), + NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true), + EmailConfirmed = table.Column<bool>(nullable: false), + PasswordHash = table.Column<string>(nullable: true), + SecurityStamp = table.Column<string>(nullable: true), + ConcurrencyStamp = table.Column<string>(nullable: true), + PhoneNumber = table.Column<string>(nullable: true), + PhoneNumberConfirmed = table.Column<bool>(nullable: false), + TwoFactorEnabled = table.Column<bool>(nullable: false), + LockoutEnd = table.Column<DateTimeOffset>(nullable: true), + LockoutEnabled = table.Column<bool>(nullable: false), + AccessFailedCount = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column<string>(nullable: false), + ClaimType = table.Column<string>(nullable: true), + ClaimValue = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column<string>(nullable: false), + ClaimType = table.Column<string>(nullable: true), + ClaimValue = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column<string>(maxLength: 128, nullable: false), + ProviderKey = table.Column<string>(maxLength: 128, nullable: false), + ProviderDisplayName = table.Column<string>(nullable: true), + UserId = table.Column<string>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column<string>(nullable: false), + RoleId = table.Column<string>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column<string>(nullable: false), + LoginProvider = table.Column<string>(maxLength: 128, nullable: false), + Name = table.Column<string>(maxLength: 128, nullable: false), + Value = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 000000000000..01098a9b9f9d --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,268 @@ +// <auto-generated /> +using System; +using BlazorWasm_CSharp.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property<string>("PasswordHash") + .HasColumnType("TEXT"); + + b.Property<string>("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property<string>("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property<string>("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("ProviderKey") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("Name") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property<string>("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 000000000000..f1d1fc3f8c40 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,277 @@ +// <auto-generated /> +using System; +using BlazorWasm_CSharp.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("00000000000000_CreateIdentitySchema")] + partial class CreateIdentitySchema + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Name") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("NormalizedName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<string>("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("nvarchar(450)"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("int"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("bit"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("bit"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property<string>("NormalizedEmail") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("NormalizedUserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property<string>("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property<string>("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<string>("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("ProviderKey") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("LoginProvider") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("Name") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 000000000000..eb6f88d7cb90 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs @@ -0,0 +1,220 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + public partial class CreateIdentitySchema : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column<string>(nullable: false), + Name = table.Column<string>(maxLength: 256, nullable: true), + NormalizedName = table.Column<string>(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column<string>(nullable: false), + UserName = table.Column<string>(maxLength: 256, nullable: true), + NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true), + Email = table.Column<string>(maxLength: 256, nullable: true), + NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true), + EmailConfirmed = table.Column<bool>(nullable: false), + PasswordHash = table.Column<string>(nullable: true), + SecurityStamp = table.Column<string>(nullable: true), + ConcurrencyStamp = table.Column<string>(nullable: true), + PhoneNumber = table.Column<string>(nullable: true), + PhoneNumberConfirmed = table.Column<bool>(nullable: false), + TwoFactorEnabled = table.Column<bool>(nullable: false), + LockoutEnd = table.Column<DateTimeOffset>(nullable: true), + LockoutEnabled = table.Column<bool>(nullable: false), + AccessFailedCount = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + RoleId = table.Column<string>(nullable: false), + ClaimType = table.Column<string>(nullable: true), + ClaimValue = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + UserId = table.Column<string>(nullable: false), + ClaimType = table.Column<string>(nullable: true), + ClaimValue = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column<string>(maxLength: 128, nullable: false), + ProviderKey = table.Column<string>(maxLength: 128, nullable: false), + ProviderDisplayName = table.Column<string>(nullable: true), + UserId = table.Column<string>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column<string>(nullable: false), + RoleId = table.Column<string>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column<string>(nullable: false), + LoginProvider = table.Column<string>(maxLength: 128, nullable: false), + Name = table.Column<string>(maxLength: 128, nullable: false), + Value = table.Column<string>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 000000000000..07026c1264ee --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,275 @@ +// <auto-generated /> +using System; +using BlazorWasm_CSharp.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace BlazorWasm_CSharp.Server.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Name") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("NormalizedName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<string>("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("nvarchar(450)"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("int"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("bit"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("bit"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property<string>("NormalizedEmail") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("NormalizedUserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property<string>("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property<string>("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property<string>("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<string>("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("ProviderKey") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property<string>("LoginProvider") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("Name") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property<string>("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs index fc9fe042124b..fd1767bd4744 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs @@ -1,18 +1,53 @@ using Microsoft.AspNetCore.Builder; +#if (IndividualLocalAuth) +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI; +#endif +#if (RequiresHttps) +using Microsoft.AspNetCore.HttpsPolicy; +#endif using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.ResponseCompression; +#if (IndividualLocalAuth) +using Microsoft.EntityFrameworkCore; +#endif +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Linq; +#if (IndividualLocalAuth) +using BlazorWasm_CSharp.Server.Data; +#endif namespace BlazorWasm_CSharp.Server { public class Startup { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { +#if (IndividualLocalAuth) + services.AddDbContext<ApplicationDbContext>(options => +#if (UseLocalDB) + options.UseSqlServer( + Configuration.GetConnectionString("DefaultConnection"))); +#else + options.UseSqlite( + Configuration.GetConnectionString("DefaultConnection"))); +#endif + services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores<ApplicationDbContext>(); + +#endif services.AddMvc(); services.AddResponseCompression(opts => { @@ -29,17 +64,41 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); +#if (IndividualLocalAuth) + app.UseDatabaseErrorPage(); +#endif app.UseBlazorDebugging(); } + else + { + app.UseExceptionHandler("/Error"); +#if (RequiresHttps) + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + } + + app.UseHttpsRedirection(); +#else + } +#endif app.UseStaticFiles(); app.UseClientSideBlazorFiles<Client.Startup>(); app.UseRouting(); +#if (IndividualLocalAuth) + app.UseAuthentication(); + app.UseAuthorization(); + +#endif app.UseEndpoints(endpoints => { - endpoints.MapDefaultControllerRoute(); +#if (IndividualLocalAuth) + endpoints.MapRazorPages(); +#endif + endpoints.MapControllers(); + endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html"); }); } diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db new file mode 100644 index 0000000000000000000000000000000000000000..ec163057f1f5433ac77fa2fea05aa4a544e6ded0 GIT binary patch literal 106496 zcmeI)UvJyi83$m|b|g!-Eay+dt-w&02G$6+i)2IL6<Ft~GL;aPDMyk68%3cp5|a>- zL`S5Yx<CuaZh{m8cDb8=g8>5y<hpn5%`UgAeTrQ+Los0I@Q@-8MOhBo42$p+;zZ;j z4_`j-dk!U&NbPpnbPVa9)$8bv^y|cOLJ$(am!w1@F++adBtQOZnY@|v7s$Ut=>532 zGl}(oKf6FT&iz2Q`C0CVrLPtbvtOpaUwnW5^ZB*p^SN)6y_v7)p3JDicS0fY&A6^& z)(?csDY39F4Bj@oE#nh)zfrIcHN)Anjb7QhZ+7hleXF*jtFIKRN};Yus<x%<OY-;~ zWvQY`a&&iDx+b%Z<@`XnG&Y7}TQ@tSF|gH_&xnEBF&YDF<YTxP8$;D<8(vrRt?v-5 zzBDF=V2cLZF&snCNMrEY^Tu*Yd}l=%WZhKIwVK{BRGJsYM_1Vw`2%vBMUP?A?loGN zZSzy3MZ1&pr`4sDxVkDl{m9Ypwv8Y&ZugPJoOiT(;lr{LPNTaq={}p0$ji^AR9E)v zl2#!<d*$+)*GRWjTXJk;v7*)L)q<+kC3$x{RDIq7cB|@6p?V-~D+fWztVu&O?-=23 zN+aEP-MU>4(^0Ba74@d(_3Xu%m#RuhsVZ7gsrjetMRH9h=a8q>yrq;CQu@V0tytJn zUM2!s@_seT5+8v-9AYAHccZzCk06`Le~?Rxw^xOPTRQfmHkpwcdf&0!<)~`oMkLG2 zr>l!8aeZBQnvT>2n*)N)*>ZMVRj}ruEZpVYo^@olj9z>J$bR#-aXev*Ez>@1>&I>x zyT#-em`C?=1?I=fR~R2LDYS5S`ANBEeTKYWNwPPyNwKy*IoVz`p=`4?OD9JQZn~em z6-hUn>VkB$<;8L79?qlQK&OM8jAZ4eQXNhLQg~=`Bi!FRoPfe!y`pO5csq(#_tWcc zSU)~ASbcD-@96D*Wc_)oftx2-Ft0juyO|`NdJkN7Z<yM~qrTB?8j-~X4n5L%txKlz zHL_>^<S0FwN;+e)6Jn_hmNQ(h-eoyx4o2?zQyJd-r%om9n?@3MSqazGFqJ_tuXN5Q zGwv6gsg$^~B0N(fW5^DMk3Ap9?a$_+LBpNj_z^>{=OJN#92A<Qc<hpHwvATN>UW*d zLFjK<w7SiHuSd%5xaR1cLw-Oh9nwe4Dzeu-v)3_VMz`N_*=jzt`i|12A1ThWotIR9 z|KLMPOb|gMr5m08cXiu-Z1q~Vbo&7x{_X>-YiRw>UH|IiA1~B!j<c&7M9p;K%<7M= zlHPQz-o#VqV<#2#-h5J2S0+#6cKCX2r%$e4a7X-UBT{&E>!HyNRUcbUjw?ad9E|w0 zrcIf@EXIyUIY`WK^7pw%XX)_h<*o{TSfN7aKKSvGkPEbX*gWyvOrGzu$c_+3WouFc zZPp#qC(V#7ol!hg_w8Jqr`r-xj!aqcL)zObbf&)7+2b^T_O}m4NYF+rY;JOexk30C z?!tw^zK{|(HiVOk>(FQ@r5*ErPj^hKYu_?$QtijFD`$9{*lhx(VV@JZ#&i?|M?S5! z`c3B!`It?Dja)d0h&q!LKi(KO=3<Z2xDmU0mVKMPx{xJrgxo(8<PTmDfB*y_009U< z00Izz00bZa0SLT40;|GoO}x&%8pWQWJLH$qM%SUg32Z(vI{J-wufO}N3^^|$_s<0R zgBJuK009U<00Izz00bZa0SG_<0<W9EFK26M?sov!V}A)i@BfpB{_%nU1Rwwb2tWV= z5P$##AOHafKwydm=>30u|DWOn<J2Gk0SG_<0uX=z1Rwwb2tWV=L;&~yQ3eoz00bZa z0SG_<0uX=z1Rwx`=@-EL|LM;$&JY3+fB*y_009U<00Izz00ba_`~Ro`2tWV=5P$## zAOHafKmY;|fWY(%;Qs&g=NM-Q0SG_<0uX=z1Rwwb2tWV=5WxL^)Bpq^009U<00Izz z00bZa0SG`~`UUX)fBJKbGlT#HAOHafKmY;|fB*y_009W#`#)*`0uX=z1Rwwb2tWV= z5P$##ATa#``2IirImQ`600Izz00bZa0SG_<0uX=z1n~d=p#~rT0SG_<0uX=z1Rwwb z2tWV=(=UMg|I?pioFN1t009U<00Izz00bZa0SG_<_y17?5P$##AOHafKmY;|fB*y_ z0D<Wj!1w>@&oRyr0uX=z1Rwwb2tWV=5P$##Ab{`xr~wE-00Izz00bZa0SG_<0uX?} z^b6qo|Mce=X9xiZKmY;|fB*y_009U<00I!e_kYv?1Rwwb2tWV=5P$##AOHafKw$a> z@cn=KbBr^D00bZa0SG_<0uX=z1Rwwb2xN0F5(~-aiKV~i{+j*U(pQUz*)P-IFTOwj z`TSb)`P{e3-pto?Pi9o%JE4&HCh<F7?6WH=adTA|{KD+Ej8D}4M!`PR3}??adR41! z*bVx(+KQ}wqgYi6bwyIOEoEPl$L=Oe6-|;OJIm5Fne{5?2g2o)SXdVZZ;u|oY~44z zc7uiz4uGw`az+H)j?oZUBaMM|Ok=n-HilwbH#?&-u+^8(h=JQN8Ut(OW4IU_19kGc z3MV31eQ8V#!4_Ty!!ZPn;anKYDe;{ZVUTrGLATNLj-k@JU>T&V?2G&Xxy_=-uxa<2 z)$8bO^HZZmyOZ;|7jv`X>Z<VcBS*j6HX_9lS<HDys~0{jD{+;S%}C_s=TfRG`*lgH zke|JBdChC2F{&*&wy{{zYV~SC)#{SGyB)25S=z0tJB8|jw5=QjC9@_C3)nkGxSP^Q zH(s}{-!L7eN>x#BYF^J?jCrZ5l$5HX6_uKQy6$dNlAJ@H4yY}qtdPN1EYymHE#+k* zpe65Dvn=ru_`@M40(ZCZ5o9y@4{}NI_NtI@OUHiHHXWm(_Z`b!j;c0pM6$e`dm;Qw zTwfQSrXw}MMr*J+Th5NFis9h)GVd<$_N*hbW%S|;K=zxrjpGShY?=09TR(Qo*exc% zz&yH_D=<G+zQXv3Nuh<q%TLNR>oes2N|L>qO^UVk$;tMj31yqDSvomdNYQjZc`K4` zHq`~`X3LA?(mk9<y>!z-PDZkFQ>hLo0VzB*xe@N~9Zo=DuU=6#a=aZytNZD7H>@8Y z8mvCJ)pzuEKeGP3)xgaYESOiFx!p{XPQ3>%yEja2<5Az}HjT*Q0*4-Hyw)XC`5M_X ze{z%_O(mVN*a@*z2Fn?)SMQTS&`jo-mriAP@1HuAwD0p=IfkhWf_bHLKACa9*i5Cw zl@;Nc5*b5wFnsL!IBtJ74@q;E&G93KT+c(o{x~Q!N%7bv-E14JqSfy@ql3`jv}kpk z{a%lh+i}g&JBR#$QaYrMm{nx2duFd=#Efpg<FeI!X!RYXOFvSaXFKoXfWLq6Atfe= zppnvzPXD{QZ9lepty{YNfDeE7fz>s%e&?=#_3@7vYB<N))eNF$I&o(8$5u&iI#zGu zsq?Xu3VLroDXJ@zr*S)cy|&XQS1-6D{<IM(yt?(!=!U9~Ehop7AZrdr{8`hc%wHB` zFSK%ynBnB_bC1r_W3LK+SfN7aKKSvGkPEbX*gWyvOrGzu$c_+3WouFcZPp#qC(V#7 zol!hg_w8Jqr`r-xj!aqcL)zObbf&)7+2b^T_O}m4NYF+rY;JOexk30C?!tw^zK{|( zHiVOk>(FQ@r5*ErPj^hKYu_?$QtijFD`$9{*lhx(VV@JZ#&i?|M?S5!`c3B!`It?D zWs||M8i|NHlN3MR7&qo(kJGpjyLy&<kDsUC<#GR?|BVKgAOHafKmY;|fB*y_009U< z00Pq}kR>OzIRBf(Qg!L#;%^uJv+(DIOPN1qGU-327w7*%8t{Su1Rwwb2tWV=p1`5V z9`{;tpV9H}4u&50qO0sTy;~}KntFS0_`n~xb@-_-cOP<#CG^ynzpb4A!_}1dHhI7- z?H<v+(HcG6&%MKW4;BX7OgIR;Yn%V<jR{XP(qO_56S_B?ME;;LPcyRJqA_^)&w?ij z@h~MGresfy<o`zxQ~t>3?oO*qDLjiAeG-z6YjRKcb$u4|M?ao-y1M8-;en?yM;`Y0 zKYSV!_y6&c4gwH>00bZa0SG_<0uX=z1RyZ|0{H$v{W-=NLI45~fB*y_009U<00Izz H00jOE{cSD9 literal 0 HcmV?d00001 diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json new file mode 100644 index 000000000000..8983e0fc1c5e --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json new file mode 100644 index 000000000000..fbfae3faeef8 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json @@ -0,0 +1,19 @@ +{ +////#if (IndividualLocalAuth) +// "ConnectionStrings": { +////#if (UseLocalDB) +// "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true" +////#else +// "DefaultConnection": "DataSource=app.db" +////#endif +// }, +////#endif + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs new file mode 100644 index 000000000000..de28f359b482 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs @@ -0,0 +1,18 @@ +namespace BlazorWasm_CSharp.Shared.Authorization +{ + public class ClaimValue + { + public ClaimValue() + { + } + + public ClaimValue(string type, string value) + { + Type = type; + Value = value; + } + + public string Type { get; set; } + public string Value { get; set; } + } +} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs new file mode 100644 index 000000000000..c21d8b50d604 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; + +namespace BlazorWasm_CSharp.Shared.Authorization +{ + public class UserInfo + { + public static readonly UserInfo Anonymous = new UserInfo(); + + public bool IsAuthenticated { get; set; } + + public string NameClaimType { get; set; } + + public string RoleClaimType { get; set; } + + public ICollection<ClaimValue> Claims { get; set; } + } +} diff --git a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs index 41cb82ac21ec..238385bf17e0 100644 --- a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs @@ -1,6 +1,7 @@ // 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.Net; using System.Threading; @@ -90,7 +91,64 @@ public async Task BlazorWasmHostedTemplate_Works() } } - protected async Task BuildAndRunTest(string appName, Project project) + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task BlazorWasmHostedTemplate_IndividualAuth_Works(bool useLocalDb) + { + var project = await ProjectFactory.GetOrCreateProject("blazorhostedindividual" + (useLocalDb ? "uld" : ""), Output); + + var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "--hosted", "-au", "Individual", useLocalDb ? "-uld" : "" }); + Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); + + var serverProject = GetSubProject(project, "Server", $"{project.ProjectName}.Server"); + + var serverProjectFileContents = ReadFile(serverProject.TemplateOutputDir, $"{serverProject.ProjectName}.csproj"); + if (!useLocalDb) + { + Assert.Contains(".db", serverProjectFileContents); + } + var publishResult = await serverProject.RunDotNetPublishAsync(); + Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", serverProject, publishResult)); + + // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release + // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build + // later, while the opposite is not true. + + var buildResult = await serverProject.RunDotNetBuildAsync(); + Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", serverProject, buildResult)); + + var migrationsResult = await serverProject.RunDotNetEfCreateMigrationAsync("blazorwasm"); + Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", serverProject, migrationsResult)); + serverProject.AssertEmptyMigration("blazorwasm"); + + if (useLocalDb) + { + using var dbUpdateResult = await serverProject.RunDotNetEfUpdateDatabaseAsync(); + Assert.True(0 == dbUpdateResult.ExitCode, ErrorMessages.GetFailedProcessMessage("update database", serverProject, dbUpdateResult)); + } + + await BuildAndRunTest(project.ProjectName, serverProject, usesAuth: true); + + using var aspNetProcess = serverProject.StartPublishedProjectAsync(); + + Assert.False( + aspNetProcess.Process.HasExited, + ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", serverProject, aspNetProcess.Process)); + + await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); + if (BrowserFixture.IsHostAutomationSupported()) + { + aspNetProcess.VisitInBrowser(Browser); + TestBasicNavigation(project.ProjectName, usesAuth: true); + } + else + { + BrowserFixture.EnforceSupportedConfigurations(); + } + } + + protected async Task BuildAndRunTest(string appName, Project project, bool usesAuth = false) { using var aspNetProcess = project.StartBuiltProjectAsync(); @@ -102,7 +160,7 @@ protected async Task BuildAndRunTest(string appName, Project project) if (BrowserFixture.IsHostAutomationSupported()) { aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(appName); + TestBasicNavigation(appName, usesAuth); } else { @@ -110,7 +168,7 @@ protected async Task BuildAndRunTest(string appName, Project project) } } - private void TestBasicNavigation(string appName) + private void TestBasicNavigation(string appName, bool usesAuth = false) { // Give components.server enough time to load so that it can replace // the prerendered content before we start making assertions. @@ -133,6 +191,40 @@ private void TestBasicNavigation(string appName) Browser.FindElement(By.CssSelector("p+button")).Click(); Browser.Equal("Current count: 1", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); + if (usesAuth) + { + Browser.FindElement(By.PartialLinkText("Log in")).Click(); + Browser.Contains("/Identity/Account/Login", () => Browser.Url); + + Browser.FindElement(By.PartialLinkText("Register as a new user")).Click(); + + var userName = $"{Guid.NewGuid()}@example.com"; + var password = $"!Test.Password1$"; + Browser.Exists(By.Name("Input.Email")); + Browser.FindElement(By.Name("Input.Email")).SendKeys(userName); + Browser.FindElement(By.Name("Input.Password")).SendKeys(password); + Browser.FindElement(By.Name("Input.ConfirmPassword")).SendKeys(password); + Browser.FindElement(By.Id("registerSubmit")).Click(); + + // We will be redirected to the RegisterConfirmation + Browser.Contains("/Identity/Account/RegisterConfirmation", () => Browser.Url); + Browser.FindElement(By.PartialLinkText("Click here to confirm your account")).Click(); + + // We will be redirected to the ConfirmEmail + Browser.Contains("/Identity/Account/ConfirmEmail", () => Browser.Url); + + // Now we can login + Browser.FindElement(By.PartialLinkText("Login")).Click(); + Browser.Exists(By.Name("Input.Email")); + Browser.FindElement(By.Name("Input.Email")).SendKeys(userName); + Browser.FindElement(By.Name("Input.Password")).SendKeys(password); + Browser.FindElement(By.Id("login-submit")).Click(); + + // Need to navigate to fetch page + Browser.Navigate().GoToUrl(new Uri(Browser.Url).GetLeftPart(UriPartial.Authority)); + Browser.Equal(appName.Trim(), () => Browser.Title.Trim()); + } + // Can navigate to the 'fetch data' page Browser.FindElement(By.PartialLinkText("Fetch data")).Click(); Browser.Contains("fetchdata", () => Browser.Url); @@ -143,6 +235,15 @@ private void TestBasicNavigation(string appName) Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count); } + private string ReadFile(string basePath, string path) + { + var fullPath = Path.Combine(basePath, path); + var doesExist = File.Exists(fullPath); + + Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}"); + return File.ReadAllText(Path.Combine(basePath, path)); + } + private Project GetSubProject(Project project, string projectDirectory, string projectName) { var subProjectDirectory = Path.Combine(project.TemplateOutputDir, projectDirectory); From 1f61fc6cb148dd3657c8d9f432c1f9423563ce7d Mon Sep 17 00:00:00 2001 From: William Godbe <wigodbe@microsoft.com> Date: Fri, 17 Jan 2020 15:56:08 -0800 Subject: [PATCH 050/322] Update dependencies from dotnet/blazor (#18424) * Update dependencies from dotnet/blazor * Update version of blazor package used * Removed obsolete WipedMethod invocation test * react to mono.wasm to dotnet.wasm rename * Leftover code cleanup --- eng/Version.Details.xml | 8 ++------ eng/Versions.props | 2 +- .../src/targets/Blazor.MonoRuntime.props | 2 +- .../BuildIntegrationTest.cs | 8 ++++---- .../PublishIntegrationTest.cs | 20 +++++++++---------- .../testassets/MonoSanity/wwwroot/index.html | 18 ----------------- .../testassets/MonoSanity/wwwroot/loader.js | 4 ++-- .../testassets/MonoSanityClient/Examples.cs | 5 ----- .../Web.JS/dist/Release/blazor.server.js | 13 +++++++++--- .../Web.JS/dist/Release/blazor.webassembly.js | 2 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 8 ++++---- .../test/E2ETest/Tests/MonoSanityTest.cs | 8 -------- 12 files changed, 35 insertions(+), 63 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e93f24e28bf2..f5b17af05a3e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,9 +9,9 @@ --> <Dependencies> <ProductDependencies> - <Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="3.1.0-preview4.19578.1"> + <Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="3.2.0-preview1.20067.1"> <Uri>https://github.com/aspnet/Blazor</Uri> - <Sha>9ff01af4257317a90b64959fe1c87aef3da4a36f</Sha> + <Sha>dd7fb4d3931d556458f62642c2edfc59f6295bfb</Sha> </Dependency> <Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.1.0-rtm.19573.1"> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri> @@ -281,10 +281,6 @@ <Uri>https://github.com/aspnet/Extensions</Uri> <Sha>1c5c7777ea9a19d54ab67ec1521665c99460efc5</Sha> </Dependency> - <Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.1.0-rtm.19572.8" CoherentParentDependency="Microsoft.EntityFrameworkCore"> - <Uri>https://github.com/aspnet/Extensions</Uri> - <Sha>1c5c7777ea9a19d54ab67ec1521665c99460efc5</Sha> - </Dependency> <Dependency Name="Microsoft.JSInterop" Version="3.1.0" CoherentParentDependency="Microsoft.EntityFrameworkCore" Pinned="true"> <Uri>https://github.com/aspnet/Extensions</Uri> <Sha>1c5c7777ea9a19d54ab67ec1521665c99460efc5</Sha> diff --git a/eng/Versions.props b/eng/Versions.props index e1dab327ee4f..5f4be96aee8b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -97,7 +97,7 @@ <!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 --> <MicrosoftNETCorePlatformsPackageVersion>3.1.0</MicrosoftNETCorePlatformsPackageVersion> <!-- Packages from aspnet/Blazor --> - <MicrosoftAspNetCoreBlazorMonoPackageVersion>3.1.0-preview4.19578.1</MicrosoftAspNetCoreBlazorMonoPackageVersion> + <MicrosoftAspNetCoreBlazorMonoPackageVersion>3.2.0-preview1.20067.1</MicrosoftAspNetCoreBlazorMonoPackageVersion> <!-- Packages from aspnet/Extensions --> <InternalAspNetCoreAnalyzersPackageVersion>3.1.0-rtm.19575.5</InternalAspNetCoreAnalyzersPackageVersion> <MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.1.0-rtm.19575.5</MicrosoftAspNetCoreAnalyzerTestingPackageVersion> diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props index dc6926924bfe..f49c1f8f2ff5 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.props @@ -6,7 +6,7 @@ <PropertyGroup Label="Blazor build outputs"> <MonoLinkerI18NAssemblies>none</MonoLinkerI18NAssemblies> <!-- 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 --exclude-feature sre -v false -c link -u link -b true</AdditionalMonoLinkerOptions> + <AdditionalMonoLinkerOptions>--disable-opt unreachablebodies --verbose --strip-security true --exclude-feature com -v false -c link -u link -b true</AdditionalMonoLinkerOptions> <BaseBlazorDistPath>dist\</BaseBlazorDistPath> <BaseBlazorPackageContentOutputPath>$(BaseBlazorDistPath)_content\</BaseBlazorPackageContentOutputPath> <BaseBlazorRuntimeOutputPath>$(BaseBlazorDistPath)_framework\</BaseBlazorRuntimeOutputPath> diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs index 027fe5999068..f3148b1a0b98 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs @@ -22,8 +22,8 @@ public async Task Build_WithDefaultSettings_Works() Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. } @@ -65,8 +65,8 @@ public async Task Build_WithLinkOnBuildDisabled_Works() Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. } diff --git a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs index f1f554d3b9dc..3556f119f405 100644 --- a/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -23,8 +23,8 @@ public async Task Publish_WithDefaultSettings_Works() Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. @@ -57,8 +57,8 @@ public async Task Publish_WithNoBuild_Works() Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. @@ -96,8 +96,8 @@ public async Task Publish_WithLinkOnBuildDisabled_Works() Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. @@ -158,8 +158,8 @@ public async Task Publish_HostedApp_Works() var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. @@ -201,8 +201,8 @@ public async Task Publish_HostedApp_WithNoBuild_Works() var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm"); - Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.wasm"); + Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "dotnet.js"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll"); Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output. diff --git a/src/Components/Blazor/testassets/MonoSanity/wwwroot/index.html b/src/Components/Blazor/testassets/MonoSanity/wwwroot/index.html index c4d1ab60e25c..8a42e8e5d1c4 100644 --- a/src/Components/Blazor/testassets/MonoSanity/wwwroot/index.html +++ b/src/Components/Blazor/testassets/MonoSanity/wwwroot/index.html @@ -36,14 +36,6 @@ </form> </fieldset> - <fieldset> - <legend>Invoke wiped method</legend> - <form id="invokeWipedMethod"> - <button type="submit" disabled>Go</button> - <div><textarea rows="5" cols="80" readonly id="invokeWipedMethodStackTrace"></textarea></div> - </form> - </fieldset> - <fieldset> <legend>Call JS from .NET</legend> <form id="callJs"> @@ -111,16 +103,6 @@ } }; - el('invokeWipedMethod').onsubmit = function (evt) { - evt.preventDefault(); - try { - invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'InvokeWipedMethod', []); - el('invokeWipedMethodStackTrace').value = 'WARNING: No exception occurred'; - } catch (ex) { - el('invokeWipedMethodStackTrace').value = ex.toString(); - } - }; - el('callJs').onsubmit = function (evt) { evt.preventDefault(); var expression = el('callJsEvalExpression').value; diff --git a/src/Components/Blazor/testassets/MonoSanity/wwwroot/loader.js b/src/Components/Blazor/testassets/MonoSanity/wwwroot/loader.js index 48d4530d3e63..328acacdff97 100644 --- a/src/Components/Blazor/testassets/MonoSanity/wwwroot/loader.js +++ b/src/Components/Blazor/testassets/MonoSanity/wwwroot/loader.js @@ -12,7 +12,7 @@ window.initMono = function initMono(loadAssemblyUrls, onReadyCallback) { window.Module = { locateFile: function (fileName) { - return fileName === 'mono.wasm' ? '/_framework/wasm/mono.wasm' : fileName; + return fileName === 'dotnet.wasm' ? '/_framework/wasm/dotnet.wasm' : fileName; }, onRuntimeInitialized: function () { var allAssemblyUrls = loadAssemblyUrls.concat([ @@ -117,7 +117,7 @@ } var scriptElem = document.createElement('script'); - scriptElem.src = '/_framework/wasm/mono.js'; + scriptElem.src = '/_framework/wasm/dotnet.js'; document.body.appendChild(scriptElem); } diff --git a/src/Components/Blazor/testassets/MonoSanityClient/Examples.cs b/src/Components/Blazor/testassets/MonoSanityClient/Examples.cs index 8023ded4d9d3..1d56128e3546 100644 --- a/src/Components/Blazor/testassets/MonoSanityClient/Examples.cs +++ b/src/Components/Blazor/testassets/MonoSanityClient/Examples.cs @@ -31,11 +31,6 @@ public static void TriggerException(string message) throw new InvalidOperationException(message); } - public static void InvokeWipedMethod() - { - new HttpClientHandler().Dispose(); - } - public static string EvaluateJavaScript(string expression) { var result = InternalCalls.InvokeJSUnmarshalled<string, string, object, object>(out var exceptionMessage, "evaluateJsExpression", expression, null, null); diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index 36050055b123..400db6164b83 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -1,15 +1,22 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=49)}([function(e,t,n){"use strict";var r;n.d(t,"a",function(){return r}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(r||(r={}))},function(e,t,n){"use strict";n.d(t,"a",function(){return s}),n.d(t,"c",function(){return c}),n.d(t,"f",function(){return u}),n.d(t,"g",function(){return l}),n.d(t,"h",function(){return f}),n.d(t,"e",function(){return h}),n.d(t,"d",function(){return p}),n.d(t,"b",function(){return d});var r=n(0),o=n(7),i=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},a=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},s=function(){function e(){}return e.isRequired=function(e,t){if(null==e)throw new Error("The '"+t+"' argument is required.")},e.isIn=function(e,t,n){if(!(e in t))throw new Error("Unknown "+n+" value: "+e+".")},e}(),c=function(){function e(){}return Object.defineProperty(e,"isBrowser",{get:function(){return"object"==typeof window},enumerable:!0,configurable:!0}),Object.defineProperty(e,"isWebWorker",{get:function(){return"object"==typeof self&&"importScripts"in self},enumerable:!0,configurable:!0}),Object.defineProperty(e,"isNode",{get:function(){return!this.isBrowser&&!this.isWebWorker},enumerable:!0,configurable:!0}),e}();function u(e,t){var n="";return l(e)?(n="Binary data of length "+e.byteLength,t&&(n+=". Content: '"+function(e){var t=new Uint8Array(e),n="";return t.forEach(function(e){n+="0x"+(e<16?"0":"")+e.toString(16)+" "}),n.substr(0,n.length-1)}(e)+"'")):"string"==typeof e&&(n="String data of length "+e.length,t&&(n+=". Content: '"+e+"'")),n}function l(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}function f(e,t,n,o,s,c,f){return i(this,void 0,void 0,function(){var i,h,p,d,g;return a(this,function(a){switch(a.label){case 0:return s?[4,s()]:[3,2];case 1:(p=a.sent())&&((i={}).Authorization="Bearer "+p,h=i),a.label=2;case 2:return e.log(r.a.Trace,"("+t+" transport) sending data. "+u(c,f)+"."),d=l(c)?"arraybuffer":"text",[4,n.post(o,{content:c,headers:h,responseType:d})];case 3:return g=a.sent(),e.log(r.a.Trace,"("+t+" transport) request complete. Response status: "+g.statusCode+"."),[2]}})})}function h(e){return void 0===e?new d(r.a.Information):null===e?o.a.instance:e.log?e:new d(e)}var p=function(){function e(e,t){this.subject=e,this.observer=t}return e.prototype.dispose=function(){var e=this.subject.observers.indexOf(this.observer);e>-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=n(3),a=n(4),s=n(43),c=n(0),u=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=function(e){function t(t){var n=e.call(this)||this;return n.logger=t,n}return u(t,e),t.prototype.send=function(e){var t=this;return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?new Promise(function(n,r){var o=new XMLHttpRequest;o.open(e.method,e.url,!0),o.withCredentials=!0,o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Content-Type","text/plain;charset=UTF-8");var s=e.headers;s&&Object.keys(s).forEach(function(e){o.setRequestHeader(e,s[e])}),e.responseType&&(o.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=function(){o.abort(),r(new i.a)}),e.timeout&&(o.timeout=e.timeout),o.onload=function(){e.abortSignal&&(e.abortSignal.onabort=null),o.status>=200&&o.status<300?n(new a.b(o.status,o.statusText,o.response||o.responseText)):r(new i.b(o.statusText,o.status))},o.onerror=function(){t.logger.log(c.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i.b(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(c.a.Warning,"Timeout from HTTP request."),r(new i.c)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(a.a),f=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),h=function(e){function t(t){var n=e.call(this)||this;return"undefined"!=typeof XMLHttpRequest?n.httpClient=new l(t):n.httpClient=new s.a(t),n}return f(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(a.a),p=n(44);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(o||(o={}));var d,g=n(1),y=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t<n.length;t++){n[t].next(e)}},e.prototype.error=function(e){for(var t=0,n=this.observers;t<n.length;t++){var r=n[t];r.error&&r.error(e)}},e.prototype.complete=function(){for(var e=0,t=this.observers;e<t.length;e++){var n=t[e];n.complete&&n.complete()}},e.prototype.subscribe=function(e){return this.observers.push(e),new g.d(this,e)},e}(),v=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},b=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},m=3e4,w=15e3;!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(d||(d={}));var E,S,C=function(){function e(e,t,n,r){var i=this;g.a.isRequired(e,"connection"),g.a.isRequired(t,"logger"),g.a.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=m,this.keepAliveIntervalInMilliseconds=w,this.logger=t,this.protocol=n,this.connection=e,this.reconnectPolicy=r,this.handshakeProtocol=new p.a,this.connection.onreceive=function(e){return i.processIncomingData(e)},this.connection.onclose=function(e){return i.connectionClosed(e)},this.callbacks={},this.methods={},this.closedCallbacks=[],this.reconnectingCallbacks=[],this.reconnectedCallbacks=[],this.invocationId=0,this.receivedHandshakeResponse=!1,this.connectionState=d.Disconnected,this.connectionStarted=!1,this.cachedPingMessage=this.protocol.writeMessage({type:o.Ping})}return e.create=function(t,n,r,o){return new e(t,n,r,o)},Object.defineProperty(e.prototype,"state",{get:function(){return this.connectionState},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"connectionId",{get:function(){return this.connection&&this.connection.connectionId||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"baseUrl",{get:function(){return this.connection.baseUrl||""},set:function(e){if(this.connectionState!==d.Disconnected&&this.connectionState!==d.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e},enumerable:!0,configurable:!0}),e.prototype.start=function(){return this.startPromise=this.startWithStateTransitions(),this.startPromise},e.prototype.startWithStateTransitions=function(){return v(this,void 0,void 0,function(){var e;return b(this,function(t){switch(t.label){case 0:if(this.connectionState!==d.Disconnected)return[2,Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."))];this.connectionState=d.Connecting,this.logger.log(c.a.Debug,"Starting HubConnection."),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,this.startInternal()];case 2:return t.sent(),this.connectionState=d.Connected,this.connectionStarted=!0,this.logger.log(c.a.Debug,"HubConnection connected successfully."),[3,4];case 3:return e=t.sent(),this.connectionState=d.Disconnected,this.logger.log(c.a.Debug,"HubConnection failed to start successfully because of error '"+e+"'."),[2,Promise.reject(e)];case 4:return[2]}})})},e.prototype.startInternal=function(){return v(this,void 0,void 0,function(){var e,t,n,r=this;return b(this,function(o){switch(o.label){case 0:return this.stopDuringStartError=void 0,this.receivedHandshakeResponse=!1,e=new Promise(function(e,t){r.handshakeResolver=e,r.handshakeRejecter=t}),[4,this.connection.start(this.protocol.transferFormat)];case 1:o.sent(),o.label=2;case 2:return o.trys.push([2,5,,7]),t={protocol:this.protocol.name,version:this.protocol.version},this.logger.log(c.a.Debug,"Sending handshake request."),[4,this.sendMessage(this.handshakeProtocol.writeHandshakeRequest(t))];case 3:return o.sent(),this.logger.log(c.a.Information,"Using HubProtocol '"+this.protocol.name+"'."),this.cleanupTimeout(),this.resetTimeoutPeriod(),this.resetKeepAliveInterval(),[4,e];case 4:if(o.sent(),this.stopDuringStartError)throw this.stopDuringStartError;return[3,7];case 5:return n=o.sent(),this.logger.log(c.a.Debug,"Hub handshake failed with error '"+n+"' during start(). Stopping HubConnection."),this.cleanupTimeout(),this.cleanupPingTimer(),[4,this.connection.stop(n)];case 6:throw o.sent(),n;case 7:return[2]}})})},e.prototype.stop=function(){return v(this,void 0,void 0,function(){var e;return b(this,function(t){switch(t.label){case 0:return e=this.startPromise,this.stopPromise=this.stopInternal(),[4,this.stopPromise];case 1:t.sent(),t.label=2;case 2:return t.trys.push([2,4,,5]),[4,e];case 3:return t.sent(),[3,5];case 4:return t.sent(),[3,5];case 5:return[2]}})})},e.prototype.stopInternal=function(e){return this.connectionState===d.Disconnected?(this.logger.log(c.a.Debug,"Call to HubConnection.stop("+e+") ignored because it is already in the disconnected state."),Promise.resolve()):this.connectionState===d.Disconnecting?(this.logger.log(c.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnecting state."),this.stopPromise):(this.connectionState=d.Disconnecting,this.logger.log(c.a.Debug,"Stopping HubConnection."),this.reconnectDelayHandle?(this.logger.log(c.a.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this.reconnectDelayHandle),this.reconnectDelayHandle=void 0,this.completeClose(),Promise.resolve()):(this.cleanupTimeout(),this.cleanupPingTimer(),this.stopDuringStartError=e||new Error("The connection was stopped before the hub handshake could complete."),this.connection.stop(e)))},e.prototype.stream=function(e){for(var t=this,n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];var i,a=this.replaceStreamingParams(n),s=a[0],c=a[1],u=this.createStreamInvocation(e,n,c),l=new y;return l.cancelCallback=function(){var e=t.createCancelInvocation(u.invocationId);return delete t.callbacks[u.invocationId],i.then(function(){return t.sendWithProtocol(e)})},this.callbacks[u.invocationId]=function(e,t){t?l.error(t):e&&(e.type===o.Completion?e.error?l.error(new Error(e.error)):l.complete():l.next(e.item))},i=this.sendWithProtocol(u).catch(function(e){l.error(e),delete t.callbacks[u.invocationId]}),this.launchStreams(s,i),l},e.prototype.sendMessage=function(e){return this.resetKeepAliveInterval(),this.connection.send(e)},e.prototype.sendWithProtocol=function(e){return this.sendMessage(this.protocol.writeMessage(e))},e.prototype.send=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=this.replaceStreamingParams(t),o=r[0],i=r[1],a=this.sendWithProtocol(this.createInvocation(e,t,!0,i));return this.launchStreams(o,a),a},e.prototype.invoke=function(e){for(var t=this,n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];var i=this.replaceStreamingParams(n),a=i[0],s=i[1],c=this.createInvocation(e,n,!1,s);return new Promise(function(e,n){t.callbacks[c.invocationId]=function(t,r){r?n(r):t&&(t.type===o.Completion?t.error?n(new Error(t.error)):e(t.result):n(new Error("Unexpected message type: "+t.type)))};var r=t.sendWithProtocol(c).catch(function(e){n(e),delete t.callbacks[c.invocationId]});t.launchStreams(a,r)})},e.prototype.on=function(e,t){e&&t&&(e=e.toLowerCase(),this.methods[e]||(this.methods[e]=[]),-1===this.methods[e].indexOf(t)&&this.methods[e].push(t))},e.prototype.off=function(e,t){if(e){e=e.toLowerCase();var n=this.methods[e];if(n)if(t){var r=n.indexOf(t);-1!==r&&(n.splice(r,1),0===n.length&&delete this.methods[e])}else delete this.methods[e]}},e.prototype.onclose=function(e){e&&this.closedCallbacks.push(e)},e.prototype.onreconnecting=function(e){e&&this.reconnectingCallbacks.push(e)},e.prototype.onreconnected=function(e){e&&this.reconnectedCallbacks.push(e)},e.prototype.processIncomingData=function(e){if(this.cleanupTimeout(),this.receivedHandshakeResponse||(e=this.processHandshakeResponse(e),this.receivedHandshakeResponse=!0),e)for(var t=0,n=this.protocol.parseMessages(e,this.logger);t<n.length;t++){var r=n[t];switch(r.type){case o.Invocation:this.invokeClientMethod(r);break;case o.StreamItem:case o.Completion:var i=this.callbacks[r.invocationId];i&&(r.type===o.Completion&&delete this.callbacks[r.invocationId],i(r));break;case o.Ping:break;case o.Close:this.logger.log(c.a.Information,"Close message received from server.");var a=r.error?new Error("Server returned an error on close: "+r.error):void 0;!0===r.allowReconnect?this.connection.stop(a):this.stopPromise=this.stopInternal(a);break;default:this.logger.log(c.a.Warning,"Invalid message type: "+r.type+".")}}this.resetTimeoutPeriod()},e.prototype.processHandshakeResponse=function(e){var t,n,r;try{r=(t=this.handshakeProtocol.parseHandshakeResponse(e))[0],n=t[1]}catch(e){var o="Error parsing handshake response: "+e;this.logger.log(c.a.Error,o);var i=new Error(o);throw this.handshakeRejecter(i),i}if(n.error){o="Server returned handshake error: "+n.error;this.logger.log(c.a.Error,o);i=new Error(o);throw this.handshakeRejecter(i),i}return this.logger.log(c.a.Debug,"Server handshake complete."),this.handshakeResolver(),r},e.prototype.resetKeepAliveInterval=function(){var e=this;this.cleanupPingTimer(),this.pingServerHandle=setTimeout(function(){return v(e,void 0,void 0,function(){return b(this,function(e){switch(e.label){case 0:if(this.connectionState!==d.Connected)return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,this.sendMessage(this.cachedPingMessage)];case 2:return e.sent(),[3,4];case 3:return e.sent(),this.cleanupPingTimer(),[3,4];case 4:return[2]}})})},this.keepAliveIntervalInMilliseconds)},e.prototype.resetTimeoutPeriod=function(){var e=this;this.connection.features&&this.connection.features.inherentKeepAlive||(this.timeoutHandle=setTimeout(function(){return e.serverTimeout()},this.serverTimeoutInMilliseconds))},e.prototype.serverTimeout=function(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))},e.prototype.invokeClientMethod=function(e){var t=this,n=this.methods[e.target.toLowerCase()];if(n){try{n.forEach(function(n){return n.apply(t,e.arguments)})}catch(t){this.logger.log(c.a.Error,"A callback for the method "+e.target.toLowerCase()+" threw error '"+t+"'.")}if(e.invocationId){var r="Server requested a response, which is not supported in this version of the client.";this.logger.log(c.a.Error,r),this.stopPromise=this.stopInternal(new Error(r))}}else this.logger.log(c.a.Warning,"No client method with the name '"+e.target+"' found.")},e.prototype.connectionClosed=function(e){this.logger.log(c.a.Debug,"HubConnection.connectionClosed("+e+") called while in state "+this.connectionState+"."),this.stopDuringStartError=this.stopDuringStartError||e||new Error("The underlying connection was closed before the hub handshake could complete."),this.handshakeResolver&&this.handshakeResolver(),this.cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this.cleanupTimeout(),this.cleanupPingTimer(),this.connectionState===d.Disconnecting?this.completeClose(e):this.connectionState===d.Connected&&this.reconnectPolicy?this.reconnect(e):this.connectionState===d.Connected&&this.completeClose(e)},e.prototype.completeClose=function(e){var t=this;if(this.connectionStarted){this.connectionState=d.Disconnected,this.connectionStarted=!1;try{this.closedCallbacks.forEach(function(n){return n.apply(t,[e])})}catch(t){this.logger.log(c.a.Error,"An onclose callback called with error '"+e+"' threw error '"+t+"'.")}}},e.prototype.reconnect=function(e){return v(this,void 0,void 0,function(){var t,n,r,o,i,a=this;return b(this,function(s){switch(s.label){case 0:if(t=Date.now(),n=0,r=void 0!==e?e:new Error("Attempting to reconnect due to a unknown error."),null===(o=this.getNextRetryDelay(n++,0,r)))return this.logger.log(c.a.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),this.completeClose(e),[2];if(this.connectionState=d.Reconnecting,e?this.logger.log(c.a.Information,"Connection reconnecting because of error '"+e+"'."):this.logger.log(c.a.Information,"Connection reconnecting."),this.onreconnecting){try{this.reconnectingCallbacks.forEach(function(t){return t.apply(a,[e])})}catch(t){this.logger.log(c.a.Error,"An onreconnecting callback called with error '"+e+"' threw error '"+t+"'.")}if(this.connectionState!==d.Reconnecting)return this.logger.log(c.a.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting."),[2]}s.label=1;case 1:return null===o?[3,7]:(this.logger.log(c.a.Information,"Reconnect attempt number "+n+" will start in "+o+" ms."),[4,new Promise(function(e){a.reconnectDelayHandle=setTimeout(e,o)})]);case 2:if(s.sent(),this.reconnectDelayHandle=void 0,this.connectionState!==d.Reconnecting)return this.logger.log(c.a.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting."),[2];s.label=3;case 3:return s.trys.push([3,5,,6]),[4,this.startInternal()];case 4:if(s.sent(),this.connectionState=d.Connected,this.logger.log(c.a.Information,"HubConnection reconnected successfully."),this.onreconnected)try{this.reconnectedCallbacks.forEach(function(e){return e.apply(a,[a.connection.connectionId])})}catch(e){this.logger.log(c.a.Error,"An onreconnected callback called with connectionId '"+this.connection.connectionId+"; threw error '"+e+"'.")}return[2];case 5:return i=s.sent(),this.logger.log(c.a.Information,"Reconnect attempt failed because of error '"+i+"'."),this.connectionState!==d.Reconnecting?(this.logger.log(c.a.Debug,"Connection left the reconnecting state during reconnect attempt. Done reconnecting."),[2]):(r=i instanceof Error?i:new Error(i.toString()),o=this.getNextRetryDelay(n++,Date.now()-t,r),[3,6]);case 6:return[3,1];case 7:return this.logger.log(c.a.Information,"Reconnect retries have been exhausted after "+(Date.now()-t)+" ms and "+n+" failed attempts. Connection disconnecting."),this.completeClose(),[2]}})})},e.prototype.getNextRetryDelay=function(e,t,n){try{return this.reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:t,previousRetryCount:e,retryReason:n})}catch(n){return this.logger.log(c.a.Error,"IRetryPolicy.nextRetryDelayInMilliseconds("+e+", "+t+") threw error '"+n+"'."),null}},e.prototype.cancelCallbacksWithError=function(e){var t=this.callbacks;this.callbacks={},Object.keys(t).forEach(function(n){(0,t[n])(null,e)})},e.prototype.cleanupPingTimer=function(){this.pingServerHandle&&clearTimeout(this.pingServerHandle)},e.prototype.cleanupTimeout=function(){this.timeoutHandle&&clearTimeout(this.timeoutHandle)},e.prototype.createInvocation=function(e,t,n,r){if(n)return{arguments:t,streamIds:r,target:e,type:o.Invocation};var i=this.invocationId;return this.invocationId++,{arguments:t,invocationId:i.toString(),streamIds:r,target:e,type:o.Invocation}},e.prototype.launchStreams=function(e,t){var n=this;if(0!==e.length){t||(t=Promise.resolve());var r=function(r){e[r].subscribe({complete:function(){t=t.then(function(){return n.sendWithProtocol(n.createCompletionMessage(r))})},error:function(e){var o;o=e instanceof Error?e.message:e&&e.toString?e.toString():"Unknown error",t=t.then(function(){return n.sendWithProtocol(n.createCompletionMessage(r,o))})},next:function(e){t=t.then(function(){return n.sendWithProtocol(n.createStreamItemMessage(r,e))})}})};for(var o in e)r(o)}},e.prototype.replaceStreamingParams=function(e){for(var t=[],n=[],r=0;r<e.length;r++){var o=e[r];if(this.isObservable(o)){var i=this.invocationId;this.invocationId++,t[i]=o,n.push(i.toString()),e.splice(r,1)}}return[t,n]},e.prototype.isObservable=function(e){return e&&e.subscribe&&"function"==typeof e.subscribe},e.prototype.createStreamInvocation=function(e,t,n){var r=this.invocationId;return this.invocationId++,{arguments:t,invocationId:r.toString(),streamIds:n,target:e,type:o.StreamInvocation}},e.prototype.createCancelInvocation=function(e){return{invocationId:e,type:o.CancelInvocation}},e.prototype.createStreamItemMessage=function(e,t){return{invocationId:e,item:t,type:o.StreamItem}},e.prototype.createCompletionMessage=function(e,t,n){return t?{error:t,invocationId:e,type:o.Completion}:{invocationId:e,result:n,type:o.Completion}},e}(),_=[0,2e3,1e4,3e4,null],I=function(){function e(e){this.retryDelays=void 0!==e?e.concat([null]):_}return e.prototype.nextRetryDelayInMilliseconds=function(e){return this.retryDelays[e.previousRetryCount]},e}();!function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(E||(E={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(S||(S={}));var T=function(){function e(){this.isAborted=!1,this.onabort=null}return e.prototype.abort=function(){this.isAborted||(this.isAborted=!0,this.onabort&&this.onabort())},Object.defineProperty(e.prototype,"signal",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"aborted",{get:function(){return this.isAborted},enumerable:!0,configurable:!0}),e}(),k=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},P=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},x=function(){function e(e,t,n,r){this.httpClient=e,this.accessTokenFactory=t,this.logger=n,this.pollAbort=new T,this.logMessageContent=r,this.running=!1,this.onreceive=null,this.onclose=null}return Object.defineProperty(e.prototype,"pollAborted",{get:function(){return this.pollAbort.aborted},enumerable:!0,configurable:!0}),e.prototype.connect=function(e,t){return k(this,void 0,void 0,function(){var n,r,o,a;return P(this,function(s){switch(s.label){case 0:if(g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.url=e,this.logger.log(c.a.Trace,"(LongPolling transport) Connecting."),t===S.Binary&&"undefined"!=typeof XMLHttpRequest&&"string"!=typeof(new XMLHttpRequest).responseType)throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");return n={abortSignal:this.pollAbort.signal,headers:{},timeout:1e5},t===S.Binary&&(n.responseType="arraybuffer"),[4,this.getAccessToken()];case 1:return r=s.sent(),this.updateHeaderToken(n,r),o=e+"&_="+Date.now(),this.logger.log(c.a.Trace,"(LongPolling transport) polling: "+o+"."),[4,this.httpClient.get(o,n)];case 2:return 200!==(a=s.sent()).statusCode?(this.logger.log(c.a.Error,"(LongPolling transport) Unexpected response code: "+a.statusCode+"."),this.closeError=new i.b(a.statusText||"",a.statusCode),this.running=!1):this.running=!0,this.receiving=this.poll(this.url,n),[2]}})})},e.prototype.getAccessToken=function(){return k(this,void 0,void 0,function(){return P(this,function(e){switch(e.label){case 0:return this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:return[2,e.sent()];case 2:return[2,null]}})})},e.prototype.updateHeaderToken=function(e,t){e.headers||(e.headers={}),t?e.headers.Authorization="Bearer "+t:e.headers.Authorization&&delete e.headers.Authorization},e.prototype.poll=function(e,t){return k(this,void 0,void 0,function(){var n,r,o,a;return P(this,function(s){switch(s.label){case 0:s.trys.push([0,,8,9]),s.label=1;case 1:return this.running?[4,this.getAccessToken()]:[3,7];case 2:n=s.sent(),this.updateHeaderToken(t,n),s.label=3;case 3:return s.trys.push([3,5,,6]),r=e+"&_="+Date.now(),this.logger.log(c.a.Trace,"(LongPolling transport) polling: "+r+"."),[4,this.httpClient.get(r,t)];case 4:return 204===(o=s.sent()).statusCode?(this.logger.log(c.a.Information,"(LongPolling transport) Poll terminated by server."),this.running=!1):200!==o.statusCode?(this.logger.log(c.a.Error,"(LongPolling transport) Unexpected response code: "+o.statusCode+"."),this.closeError=new i.b(o.statusText||"",o.statusCode),this.running=!1):o.content?(this.logger.log(c.a.Trace,"(LongPolling transport) data received. "+Object(g.f)(o.content,this.logMessageContent)+"."),this.onreceive&&this.onreceive(o.content)):this.logger.log(c.a.Trace,"(LongPolling transport) Poll timed out, reissuing."),[3,6];case 5:return a=s.sent(),this.running?a instanceof i.c?this.logger.log(c.a.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this.closeError=a,this.running=!1):this.logger.log(c.a.Trace,"(LongPolling transport) Poll errored after shutdown: "+a.message),[3,6];case 6:return[3,1];case 7:return[3,9];case 8:return this.logger.log(c.a.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this.raiseOnClose(),[7];case 9:return[2]}})})},e.prototype.send=function(e){return k(this,void 0,void 0,function(){return P(this,function(t){return this.running?[2,Object(g.h)(this.logger,"LongPolling",this.httpClient,this.url,this.accessTokenFactory,e,this.logMessageContent)]:[2,Promise.reject(new Error("Cannot send until the transport is connected"))]})})},e.prototype.stop=function(){return k(this,void 0,void 0,function(){var e,t;return P(this,function(n){switch(n.label){case 0:this.logger.log(c.a.Trace,"(LongPolling transport) Stopping polling."),this.running=!1,this.pollAbort.abort(),n.label=1;case 1:return n.trys.push([1,,5,6]),[4,this.receiving];case 2:return n.sent(),this.logger.log(c.a.Trace,"(LongPolling transport) sending DELETE request to "+this.url+"."),e={headers:{}},[4,this.getAccessToken()];case 3:return t=n.sent(),this.updateHeaderToken(e,t),[4,this.httpClient.delete(this.url,e)];case 4:return n.sent(),this.logger.log(c.a.Trace,"(LongPolling transport) DELETE request sent."),[3,6];case 5:return this.logger.log(c.a.Trace,"(LongPolling transport) Stop finished."),this.raiseOnClose(),[7];case 6:return[2]}})})},e.prototype.raiseOnClose=function(){if(this.onclose){var e="(LongPolling transport) Firing onclose event.";this.closeError&&(e+=" Error: "+this.closeError),this.logger.log(c.a.Trace,e),this.onclose(this.closeError)}},e}(),R=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},D=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},O=function(){function e(e,t,n,r,o){this.httpClient=e,this.accessTokenFactory=t,this.logger=n,this.logMessageContent=r,this.eventSourceConstructor=o,this.onreceive=null,this.onclose=null}return e.prototype.connect=function(e,t){return R(this,void 0,void 0,function(){var n,r=this;return D(this,function(o){switch(o.label){case 0:return g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.logger.log(c.a.Trace,"(SSE transport) Connecting."),this.url=e,this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(n=o.sent())&&(e+=(e.indexOf("?")<0?"?":"&")+"access_token="+encodeURIComponent(n)),o.label=2;case 2:return[2,new Promise(function(n,o){var i=!1;if(t===S.Text){var a;if(g.c.isBrowser||g.c.isWebWorker)a=new r.eventSourceConstructor(e,{withCredentials:!0});else{var s=r.httpClient.getCookieString(e);a=new r.eventSourceConstructor(e,{withCredentials:!0,headers:{Cookie:s}})}try{a.onmessage=function(e){if(r.onreceive)try{r.logger.log(c.a.Trace,"(SSE transport) data received. "+Object(g.f)(e.data,r.logMessageContent)+"."),r.onreceive(e.data)}catch(e){return void r.close(e)}},a.onerror=function(e){var t=new Error(e.data||"Error occurred");i?r.close(t):o(t)},a.onopen=function(){r.logger.log(c.a.Information,"SSE connected to "+r.url),r.eventSource=a,i=!0,n()}}catch(e){return void o(e)}}else o(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"))})]}})})},e.prototype.send=function(e){return R(this,void 0,void 0,function(){return D(this,function(t){return this.eventSource?[2,Object(g.h)(this.logger,"SSE",this.httpClient,this.url,this.accessTokenFactory,e,this.logMessageContent)]:[2,Promise.reject(new Error("Cannot send until the transport is connected"))]})})},e.prototype.stop=function(){return this.close(),Promise.resolve()},e.prototype.close=function(e){this.eventSource&&(this.eventSource.close(),this.eventSource=void 0,this.onclose&&this.onclose(e))},e}(),L=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},M=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},A=function(){function e(e,t,n,r,o){this.logger=n,this.accessTokenFactory=t,this.logMessageContent=r,this.webSocketConstructor=o,this.httpClient=e,this.onreceive=null,this.onclose=null}return e.prototype.connect=function(e,t){return L(this,void 0,void 0,function(){var n,r=this;return M(this,function(o){switch(o.label){case 0:return g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.logger.log(c.a.Trace,"(WebSockets transport) Connecting."),this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(n=o.sent())&&(e+=(e.indexOf("?")<0?"?":"&")+"access_token="+encodeURIComponent(n)),o.label=2;case 2:return[2,new Promise(function(n,o){var i;e=e.replace(/^http/,"ws");var a=r.httpClient.getCookieString(e),s=!1;g.c.isNode&&a&&(i=new r.webSocketConstructor(e,void 0,{headers:{Cookie:""+a}})),i||(i=new r.webSocketConstructor(e)),t===S.Binary&&(i.binaryType="arraybuffer"),i.onopen=function(t){r.logger.log(c.a.Information,"WebSocket connected to "+e+"."),r.webSocket=i,s=!0,n()},i.onerror=function(e){var t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:new Error("There was an error with the transport."),o(t)},i.onmessage=function(e){r.logger.log(c.a.Trace,"(WebSockets transport) data received. "+Object(g.f)(e.data,r.logMessageContent)+"."),r.onreceive&&r.onreceive(e.data)},i.onclose=function(e){if(s)r.close(e);else{var t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:new Error("There was an error with the transport."),o(t)}}})]}})})},e.prototype.send=function(e){return this.webSocket&&this.webSocket.readyState===this.webSocketConstructor.OPEN?(this.logger.log(c.a.Trace,"(WebSockets transport) sending data. "+Object(g.f)(e,this.logMessageContent)+"."),this.webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")},e.prototype.stop=function(){return this.webSocket&&(this.webSocket.onclose=function(){},this.webSocket.onmessage=function(){},this.webSocket.onerror=function(){},this.webSocket.close(),this.webSocket=void 0,this.close(void 0)),Promise.resolve()},e.prototype.close=function(e){this.logger.log(c.a.Trace,"(WebSockets transport) socket closed."),this.onclose&&(!e||!1!==e.wasClean&&1e3===e.code?this.onclose():this.onclose(new Error("WebSocket closed with status code: "+e.code+" ("+e.reason+").")))},e}(),B=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},j=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},U=null,N=null;if(g.c.isNode){var F=require;U=F("ws"),N=F("eventsource")}var H=function(){function e(e,t){void 0===t&&(t={}),this.features={},this.negotiateVersion=1,g.a.isRequired(e,"url"),this.logger=Object(g.e)(t.logger),this.baseUrl=this.resolveUrl(e),(t=t||{}).logMessageContent=t.logMessageContent||!1,g.c.isNode||"undefined"==typeof WebSocket||t.WebSocket?g.c.isNode&&!t.WebSocket&&U&&(t.WebSocket=U):t.WebSocket=WebSocket,g.c.isNode||"undefined"==typeof EventSource||t.EventSource?g.c.isNode&&!t.EventSource&&void 0!==N&&(t.EventSource=N):t.EventSource=EventSource,this.httpClient=t.httpClient||new h(this.logger),this.connectionState="Disconnected",this.connectionStarted=!1,this.options=t,this.onreceive=null,this.onclose=null}return e.prototype.start=function(e){return B(this,void 0,void 0,function(){var t;return j(this,function(n){switch(n.label){case 0:return e=e||S.Binary,g.a.isIn(e,S,"transferFormat"),this.logger.log(c.a.Debug,"Starting connection with transfer format '"+S[e]+"'."),"Disconnected"!==this.connectionState?[2,Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."))]:(this.connectionState="Connecting ",this.startInternalPromise=this.startInternal(e),[4,this.startInternalPromise]);case 1:return n.sent(),"Disconnecting"!==this.connectionState?[3,3]:(t="Failed to start the HttpConnection before stop() was called.",this.logger.log(c.a.Error,t),[4,this.stopPromise]);case 2:return n.sent(),[2,Promise.reject(new Error(t))];case 3:if("Connected"!==this.connectionState)return t="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!",this.logger.log(c.a.Error,t),[2,Promise.reject(new Error(t))];n.label=4;case 4:return this.connectionStarted=!0,[2]}})})},e.prototype.send=function(e){return"Connected"!==this.connectionState?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this.sendQueue||(this.sendQueue=new q(this.transport)),this.sendQueue.send(e))},e.prototype.stop=function(e){return B(this,void 0,void 0,function(){var t=this;return j(this,function(n){switch(n.label){case 0:return"Disconnected"===this.connectionState?(this.logger.log(c.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnected state."),[2,Promise.resolve()]):"Disconnecting"===this.connectionState?(this.logger.log(c.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnecting state."),[2,this.stopPromise]):(this.connectionState="Disconnecting",this.stopPromise=new Promise(function(e){t.stopPromiseResolver=e}),[4,this.stopInternal(e)]);case 1:return n.sent(),[4,this.stopPromise];case 2:return n.sent(),[2]}})})},e.prototype.stopInternal=function(e){return B(this,void 0,void 0,function(){var t,n;return j(this,function(r){switch(r.label){case 0:this.stopError=e,r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.startInternalPromise];case 2:return r.sent(),[3,4];case 3:return r.sent(),[3,4];case 4:if(!this.sendQueue)return[3,9];r.label=5;case 5:return r.trys.push([5,7,,8]),[4,this.sendQueue.stop()];case 6:return r.sent(),[3,8];case 7:return t=r.sent(),this.logger.log(c.a.Error,"TransportSendQueue.stop() threw error '"+t+"'."),[3,8];case 8:this.sendQueue=void 0,r.label=9;case 9:if(!this.transport)return[3,14];r.label=10;case 10:return r.trys.push([10,12,,13]),[4,this.transport.stop()];case 11:return r.sent(),[3,13];case 12:return n=r.sent(),this.logger.log(c.a.Error,"HttpConnection.transport.stop() threw error '"+n+"'."),this.stopConnection(),[3,13];case 13:return this.transport=void 0,[3,15];case 14:this.logger.log(c.a.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed."),this.stopConnection(),r.label=15;case 15:return[2]}})})},e.prototype.startInternal=function(e){return B(this,void 0,void 0,function(){var t,n,r,o,i,a;return j(this,function(s){switch(s.label){case 0:t=this.baseUrl,this.accessTokenFactory=this.options.accessTokenFactory,s.label=1;case 1:return s.trys.push([1,12,,13]),this.options.skipNegotiation?this.options.transport!==E.WebSockets?[3,3]:(this.transport=this.constructTransport(E.WebSockets),[4,this.startTransport(t,e)]):[3,5];case 2:return s.sent(),[3,4];case 3:throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");case 4:return[3,11];case 5:n=null,r=0,o=function(){var e;return j(this,function(o){switch(o.label){case 0:return[4,i.getNegotiationResponse(t)];case 1:if(n=o.sent(),"Disconnecting"===i.connectionState||"Disconnected"===i.connectionState)throw new Error("The connection was stopped during negotiation.");if(n.error)throw new Error(n.error);if(n.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");return n.url&&(t=n.url),n.accessToken&&(e=n.accessToken,i.accessTokenFactory=function(){return e}),r++,[2]}})},i=this,s.label=6;case 6:return[5,o()];case 7:s.sent(),s.label=8;case 8:if(n.url&&r<100)return[3,6];s.label=9;case 9:if(100===r&&n.url)throw new Error("Negotiate redirection limit exceeded.");return[4,this.createTransport(t,this.options.transport,n,e)];case 10:s.sent(),s.label=11;case 11:return this.transport instanceof x&&(this.features.inherentKeepAlive=!0),"Connecting "===this.connectionState&&(this.logger.log(c.a.Debug,"The HttpConnection connected successfully."),this.connectionState="Connected"),[3,13];case 12:return a=s.sent(),this.logger.log(c.a.Error,"Failed to start the connection: "+a),this.connectionState="Disconnected",this.transport=void 0,[2,Promise.reject(a)];case 13:return[2]}})})},e.prototype.getNegotiationResponse=function(e){return B(this,void 0,void 0,function(){var t,n,r,o,i,a,s;return j(this,function(u){switch(u.label){case 0:return this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(r=u.sent())&&((t={}).Authorization="Bearer "+r,n=t),u.label=2;case 2:o=this.resolveNegotiateUrl(e),this.logger.log(c.a.Debug,"Sending negotiation request: "+o+"."),u.label=3;case 3:return u.trys.push([3,5,,6]),[4,this.httpClient.post(o,{content:"",headers:n})];case 4:return 200!==(i=u.sent()).statusCode?[2,Promise.reject(new Error("Unexpected status code returned from negotiate "+i.statusCode))]:((!(a=JSON.parse(i.content)).negotiateVersion||a.negotiateVersion<1)&&(a.connectionToken=a.connectionId),[2,a]);case 5:return s=u.sent(),this.logger.log(c.a.Error,"Failed to complete negotiation with the server: "+s),[2,Promise.reject(s)];case 6:return[2]}})})},e.prototype.createConnectUrl=function(e,t){return t?e+(-1===e.indexOf("?")?"?":"&")+"id="+t:e},e.prototype.createTransport=function(e,t,n,r){return B(this,void 0,void 0,function(){var o,i,a,s,u,l,f,h,p,d,g;return j(this,function(y){switch(y.label){case 0:return o=this.createConnectUrl(e,n.connectionToken),this.isITransport(t)?(this.logger.log(c.a.Debug,"Connection was provided an instance of ITransport, using that directly."),this.transport=t,[4,this.startTransport(o,r)]):[3,2];case 1:return y.sent(),this.connectionId=n.connectionId,[2];case 2:i=[],a=n.availableTransports||[],s=n,u=0,l=a,y.label=3;case 3:return u<l.length?(f=l[u],(h=this.resolveTransportOrError(f,t,r))instanceof Error?(i.push(f.transport+" failed: "+h),[3,12]):[3,4]):[3,13];case 4:if(!this.isITransport(h))return[3,12];if(this.transport=h,s)return[3,9];y.label=5;case 5:return y.trys.push([5,7,,8]),[4,this.getNegotiationResponse(e)];case 6:return s=y.sent(),[3,8];case 7:return p=y.sent(),[2,Promise.reject(p)];case 8:o=this.createConnectUrl(e,s.connectionToken),y.label=9;case 9:return y.trys.push([9,11,,12]),[4,this.startTransport(o,r)];case 10:return y.sent(),this.connectionId=s.connectionId,[2];case 11:return d=y.sent(),this.logger.log(c.a.Error,"Failed to start the transport '"+f.transport+"': "+d),s=void 0,i.push(f.transport+" failed: "+d),"Connecting "!==this.connectionState?(g="Failed to select transport before stop() was called.",this.logger.log(c.a.Debug,g),[2,Promise.reject(new Error(g))]):[3,12];case 12:return u++,[3,3];case 13:return i.length>0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}})})},e.prototype.constructTransport=function(e){switch(e){case E.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new A(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket);case E.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new O(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource);case E.LongPolling:return new x(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1);default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=E[e.transport];if(null==r)return this.logger.log(c.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it was disabled by the client."),new Error("'"+E[r]+"' is disabled by the client.");if(!(e.transferFormats.map(function(e){return S[e]}).indexOf(n)>=0))return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it does not support the requested transfer format '"+S[n]+"'."),new Error("'"+E[r]+"' does not support "+S[n]+".");if(r===E.WebSockets&&!this.options.WebSocket||r===E.ServerSentEvents&&!this.options.EventSource)return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it is not supported in your environment.'"),new Error("'"+E[r]+"' is not supported in your environment.");this.logger.log(c.a.Debug,"Selecting transport '"+E[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){if(this.logger.log(c.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState)if("Connecting "!==this.connectionState){if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(c.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(c.a.Information,"Connection disconnected."),this.connectionId=void 0,this.connectionState="Disconnected",this.onclose&&this.connectionStarted){this.connectionStarted=!1;try{this.onclose(e)}catch(t){this.logger.log(c.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(c.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection hasn't yet left the in the connecting state.");else this.logger.log(c.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!g.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(c.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var q=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new W,this.transportResult=new W,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new W),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return B(this,void 0,void 0,function(){var t,n,r;return j(this,function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new W,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}})})},e.concatBuffers=function(e){for(var t=e.map(function(e){return e.byteLength}).reduce(function(e,t){return e+t}),n=new Uint8Array(t),r=0,o=0,i=e;o<i.length;o++){var a=i[o];n.set(new Uint8Array(a),r),r+=a.byteLength}return n},e}(),W=function(){function e(){var e=this;this.promise=new Promise(function(t,n){var r;return r=[t,n],e.resolver=r[0],e.rejecter=r[1],r})}return e.prototype.resolve=function(){this.resolver()},e.prototype.reject=function(e){this.rejecter(e)},e}(),z=n(7),Y=n(8),J="json",K=function(){function e(){this.name=J,this.version=1,this.transferFormat=S.Text}return e.prototype.parseMessages=function(e,t){if("string"!=typeof e)throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];null===t&&(t=z.a.instance);for(var n=[],r=0,i=Y.a.parse(e);r<i.length;r++){var a=i[r],s=JSON.parse(a);if("number"!=typeof s.type)throw new Error("Invalid payload.");switch(s.type){case o.Invocation:this.isInvocationMessage(s);break;case o.StreamItem:this.isStreamItemMessage(s);break;case o.Completion:this.isCompletionMessage(s);break;case o.Ping:case o.Close:break;default:t.log(c.a.Information,"Unknown message type '"+s.type+"' ignored.");continue}n.push(s)}return n},e.prototype.writeMessage=function(e){return Y.a.write(JSON.stringify(e))},e.prototype.isInvocationMessage=function(e){this.assertNotEmptyString(e.target,"Invalid payload for Invocation message."),void 0!==e.invocationId&&this.assertNotEmptyString(e.invocationId,"Invalid payload for Invocation message.")},e.prototype.isStreamItemMessage=function(e){if(this.assertNotEmptyString(e.invocationId,"Invalid payload for StreamItem message."),void 0===e.item)throw new Error("Invalid payload for StreamItem message.")},e.prototype.isCompletionMessage=function(e){if(e.result&&e.error)throw new Error("Invalid payload for Completion message.");!e.result&&e.error&&this.assertNotEmptyString(e.error,"Invalid payload for Completion message."),this.assertNotEmptyString(e.invocationId,"Invalid payload for Completion message.")},e.prototype.assertNotEmptyString=function(e,t){if("string"!=typeof e||""===e)throw new Error(t)},e}(),V=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},X={trace:c.a.Trace,debug:c.a.Debug,info:c.a.Information,information:c.a.Information,warn:c.a.Warning,warning:c.a.Warning,error:c.a.Error,critical:c.a.Critical,none:c.a.None};var G=function(){function e(){}return e.prototype.configureLogging=function(e){if(g.a.isRequired(e,"logging"),void 0!==e.log)this.logger=e;else if("string"==typeof e){var t=function(e){var t=X[e.toLowerCase()];if(void 0!==t)return t;throw new Error("Unknown log level: "+e)}(e);this.logger=new g.b(t)}else this.logger=new g.b(e);return this},e.prototype.withUrl=function(e,t){return g.a.isRequired(e,"url"),this.url=e,this.httpConnectionOptions=V({},this.httpConnectionOptions,"object"==typeof t?t:{transport:t}),this},e.prototype.withHubProtocol=function(e){return g.a.isRequired(e,"protocol"),this.protocol=e,this},e.prototype.withAutomaticReconnect=function(e){if(this.reconnectPolicy)throw new Error("A reconnectPolicy has already been set.");return e?Array.isArray(e)?this.reconnectPolicy=new I(e):this.reconnectPolicy=e:this.reconnectPolicy=new I,this},e.prototype.build=function(){var e=this.httpConnectionOptions||{};if(void 0===e.logger&&(e.logger=this.logger),!this.url)throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");var t=new H(this.url,e);return C.create(t,this.logger||z.a.instance,this.protocol||new K,this.reconnectPolicy)},e}();n.d(t,"VERSION",function(){return Q}),n.d(t,"AbortError",function(){return i.a}),n.d(t,"HttpError",function(){return i.b}),n.d(t,"TimeoutError",function(){return i.c}),n.d(t,"HttpClient",function(){return a.a}),n.d(t,"HttpResponse",function(){return a.b}),n.d(t,"DefaultHttpClient",function(){return h}),n.d(t,"HubConnection",function(){return C}),n.d(t,"HubConnectionState",function(){return d}),n.d(t,"HubConnectionBuilder",function(){return G}),n.d(t,"MessageType",function(){return o}),n.d(t,"LogLevel",function(){return c.a}),n.d(t,"HttpTransportType",function(){return E}),n.d(t,"TransferFormat",function(){return S}),n.d(t,"NullLogger",function(){return z.a}),n.d(t,"JsonHubProtocol",function(){return K}),n.d(t,"Subject",function(){return y});var Q="0.0.0-DEV_BUILD"},function(e,t,n){"use strict";n.d(t,"b",function(){return i}),n.d(t,"c",function(){return a}),n.d(t,"a",function(){return s});var r,o=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return o(t,e),t}(Error),a=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error)},function(e,t,n){"use strict";n.d(t,"b",function(){return o}),n.d(t,"a",function(){return i});var r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},o=function(){return function(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}(),i=function(){function e(){}return e.prototype.get=function(e,t){return this.send(r({},t,{method:"GET",url:e}))},e.prototype.post=function(e,t){return this.send(r({},t,{method:"POST",url:e}))},e.prototype.delete=function(e,t){return this.send(r({},t,{method:"DELETE",url:e}))},e.prototype.getCookieString=function(e){return""},e}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),i={},a=!1;function s(e,t,n){var o=i[e];o||(o=i[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=s,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");s(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=i[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),s=r.values(o),c=r.count(o),u=t.referenceFrames(),l=r.values(u),f=t.diffReader,h=0;h<c;h++){var p=t.updatedComponentsEntry(s,h),d=f.componentId(p),g=f.edits(p);n.updateComponent(t,d,g,l)}var y=t.disposedComponentIds(),v=r.values(y),b=r.count(y);for(h=0;h<b;h++)d=t.disposedComponentIdsEntry(v,h),n.disposeComponent(d);var m=t.disposedEventHandlerIds(),w=r.values(m),E=r.count(m);for(h=0;h<E;h++){var S=t.disposedEventHandlerIdsEntry(w,h);n.disposeEventHandler(S)}a&&(a=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){a=!0}},function(e,t,n){"use strict";(function(e){ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=51)}([function(e,t,n){"use strict";var r;n.d(t,"a",function(){return r}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(r||(r={}))},function(e,t,n){"use strict";n.d(t,"a",function(){return a}),n.d(t,"c",function(){return u}),n.d(t,"f",function(){return c}),n.d(t,"g",function(){return l}),n.d(t,"h",function(){return f}),n.d(t,"e",function(){return h}),n.d(t,"d",function(){return p}),n.d(t,"b",function(){return d});var r=n(0),o=n(6),i=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},s=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},a=function(){function e(){}return e.isRequired=function(e,t){if(null==e)throw new Error("The '"+t+"' argument is required.")},e.isIn=function(e,t,n){if(!(e in t))throw new Error("Unknown "+n+" value: "+e+".")},e}(),u=function(){function e(){}return Object.defineProperty(e,"isBrowser",{get:function(){return"object"==typeof window},enumerable:!0,configurable:!0}),Object.defineProperty(e,"isWebWorker",{get:function(){return"object"==typeof self&&"importScripts"in self},enumerable:!0,configurable:!0}),Object.defineProperty(e,"isNode",{get:function(){return!this.isBrowser&&!this.isWebWorker},enumerable:!0,configurable:!0}),e}();function c(e,t){var n="";return l(e)?(n="Binary data of length "+e.byteLength,t&&(n+=". Content: '"+function(e){var t=new Uint8Array(e),n="";return t.forEach(function(e){n+="0x"+(e<16?"0":"")+e.toString(16)+" "}),n.substr(0,n.length-1)}(e)+"'")):"string"==typeof e&&(n="String data of length "+e.length,t&&(n+=". Content: '"+e+"'")),n}function l(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}function f(e,t,n,o,a,u,f){return i(this,void 0,void 0,function(){var i,h,p,d,g;return s(this,function(s){switch(s.label){case 0:return a?[4,a()]:[3,2];case 1:(p=s.sent())&&((i={}).Authorization="Bearer "+p,h=i),s.label=2;case 2:return e.log(r.a.Trace,"("+t+" transport) sending data. "+c(u,f)+"."),d=l(u)?"arraybuffer":"text",[4,n.post(o,{content:u,headers:h,responseType:d})];case 3:return g=s.sent(),e.log(r.a.Trace,"("+t+" transport) request complete. Response status: "+g.statusCode+"."),[2]}})})}function h(e){return void 0===e?new d(r.a.Information):null===e?o.a.instance:e.log?e:new d(e)}var p=function(){function e(e,t){this.subject=e,this.observer=t}return e.prototype.dispose=function(){var e=this.subject.observers.indexOf(this.observer);e>-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=n(3),s=n(4),a=n(45),u=n(0),c=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=function(e){function t(t){var n=e.call(this)||this;return n.logger=t,n}return c(t,e),t.prototype.send=function(e){var t=this;return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?new Promise(function(n,r){var o=new XMLHttpRequest;o.open(e.method,e.url,!0),o.withCredentials=!0,o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Content-Type","text/plain;charset=UTF-8");var a=e.headers;a&&Object.keys(a).forEach(function(e){o.setRequestHeader(e,a[e])}),e.responseType&&(o.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=function(){o.abort(),r(new i.a)}),e.timeout&&(o.timeout=e.timeout),o.onload=function(){e.abortSignal&&(e.abortSignal.onabort=null),o.status>=200&&o.status<300?n(new s.b(o.status,o.statusText,o.response||o.responseText)):r(new i.b(o.statusText,o.status))},o.onerror=function(){t.logger.log(u.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i.b(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(u.a.Warning,"Timeout from HTTP request."),r(new i.c)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(s.a),f=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),h=function(e){function t(t){var n=e.call(this)||this;return"undefined"!=typeof XMLHttpRequest?n.httpClient=new l(t):n.httpClient=new a.a(t),n}return f(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(s.a),p=n(46);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(o||(o={}));var d,g=n(1),y=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t<n.length;t++){n[t].next(e)}},e.prototype.error=function(e){for(var t=0,n=this.observers;t<n.length;t++){var r=n[t];r.error&&r.error(e)}},e.prototype.complete=function(){for(var e=0,t=this.observers;e<t.length;e++){var n=t[e];n.complete&&n.complete()}},e.prototype.subscribe=function(e){return this.observers.push(e),new g.d(this,e)},e}(),v=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},b=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},m=3e4,w=15e3;!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(d||(d={}));var E,S,_=function(){function e(e,t,n,r){var i=this;g.a.isRequired(e,"connection"),g.a.isRequired(t,"logger"),g.a.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=m,this.keepAliveIntervalInMilliseconds=w,this.logger=t,this.protocol=n,this.connection=e,this.reconnectPolicy=r,this.handshakeProtocol=new p.a,this.connection.onreceive=function(e){return i.processIncomingData(e)},this.connection.onclose=function(e){return i.connectionClosed(e)},this.callbacks={},this.methods={},this.closedCallbacks=[],this.reconnectingCallbacks=[],this.reconnectedCallbacks=[],this.invocationId=0,this.receivedHandshakeResponse=!1,this.connectionState=d.Disconnected,this.connectionStarted=!1,this.cachedPingMessage=this.protocol.writeMessage({type:o.Ping})}return e.create=function(t,n,r,o){return new e(t,n,r,o)},Object.defineProperty(e.prototype,"state",{get:function(){return this.connectionState},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"connectionId",{get:function(){return this.connection&&this.connection.connectionId||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"baseUrl",{get:function(){return this.connection.baseUrl||""},set:function(e){if(this.connectionState!==d.Disconnected&&this.connectionState!==d.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e},enumerable:!0,configurable:!0}),e.prototype.start=function(){return this.startPromise=this.startWithStateTransitions(),this.startPromise},e.prototype.startWithStateTransitions=function(){return v(this,void 0,void 0,function(){var e;return b(this,function(t){switch(t.label){case 0:if(this.connectionState!==d.Disconnected)return[2,Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."))];this.connectionState=d.Connecting,this.logger.log(u.a.Debug,"Starting HubConnection."),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,this.startInternal()];case 2:return t.sent(),this.connectionState=d.Connected,this.connectionStarted=!0,this.logger.log(u.a.Debug,"HubConnection connected successfully."),[3,4];case 3:return e=t.sent(),this.connectionState=d.Disconnected,this.logger.log(u.a.Debug,"HubConnection failed to start successfully because of error '"+e+"'."),[2,Promise.reject(e)];case 4:return[2]}})})},e.prototype.startInternal=function(){return v(this,void 0,void 0,function(){var e,t,n,r=this;return b(this,function(o){switch(o.label){case 0:return this.stopDuringStartError=void 0,this.receivedHandshakeResponse=!1,e=new Promise(function(e,t){r.handshakeResolver=e,r.handshakeRejecter=t}),[4,this.connection.start(this.protocol.transferFormat)];case 1:o.sent(),o.label=2;case 2:return o.trys.push([2,5,,7]),t={protocol:this.protocol.name,version:this.protocol.version},this.logger.log(u.a.Debug,"Sending handshake request."),[4,this.sendMessage(this.handshakeProtocol.writeHandshakeRequest(t))];case 3:return o.sent(),this.logger.log(u.a.Information,"Using HubProtocol '"+this.protocol.name+"'."),this.cleanupTimeout(),this.resetTimeoutPeriod(),this.resetKeepAliveInterval(),[4,e];case 4:if(o.sent(),this.stopDuringStartError)throw this.stopDuringStartError;return[3,7];case 5:return n=o.sent(),this.logger.log(u.a.Debug,"Hub handshake failed with error '"+n+"' during start(). Stopping HubConnection."),this.cleanupTimeout(),this.cleanupPingTimer(),[4,this.connection.stop(n)];case 6:throw o.sent(),n;case 7:return[2]}})})},e.prototype.stop=function(){return v(this,void 0,void 0,function(){var e;return b(this,function(t){switch(t.label){case 0:return e=this.startPromise,this.stopPromise=this.stopInternal(),[4,this.stopPromise];case 1:t.sent(),t.label=2;case 2:return t.trys.push([2,4,,5]),[4,e];case 3:return t.sent(),[3,5];case 4:return t.sent(),[3,5];case 5:return[2]}})})},e.prototype.stopInternal=function(e){return this.connectionState===d.Disconnected?(this.logger.log(u.a.Debug,"Call to HubConnection.stop("+e+") ignored because it is already in the disconnected state."),Promise.resolve()):this.connectionState===d.Disconnecting?(this.logger.log(u.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnecting state."),this.stopPromise):(this.connectionState=d.Disconnecting,this.logger.log(u.a.Debug,"Stopping HubConnection."),this.reconnectDelayHandle?(this.logger.log(u.a.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this.reconnectDelayHandle),this.reconnectDelayHandle=void 0,this.completeClose(),Promise.resolve()):(this.cleanupTimeout(),this.cleanupPingTimer(),this.stopDuringStartError=e||new Error("The connection was stopped before the hub handshake could complete."),this.connection.stop(e)))},e.prototype.stream=function(e){for(var t=this,n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];var i,s=this.replaceStreamingParams(n),a=s[0],u=s[1],c=this.createStreamInvocation(e,n,u),l=new y;return l.cancelCallback=function(){var e=t.createCancelInvocation(c.invocationId);return delete t.callbacks[c.invocationId],i.then(function(){return t.sendWithProtocol(e)})},this.callbacks[c.invocationId]=function(e,t){t?l.error(t):e&&(e.type===o.Completion?e.error?l.error(new Error(e.error)):l.complete():l.next(e.item))},i=this.sendWithProtocol(c).catch(function(e){l.error(e),delete t.callbacks[c.invocationId]}),this.launchStreams(a,i),l},e.prototype.sendMessage=function(e){return this.resetKeepAliveInterval(),this.connection.send(e)},e.prototype.sendWithProtocol=function(e){return this.sendMessage(this.protocol.writeMessage(e))},e.prototype.send=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=this.replaceStreamingParams(t),o=r[0],i=r[1],s=this.sendWithProtocol(this.createInvocation(e,t,!0,i));return this.launchStreams(o,s),s},e.prototype.invoke=function(e){for(var t=this,n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];var i=this.replaceStreamingParams(n),s=i[0],a=i[1],u=this.createInvocation(e,n,!1,a);return new Promise(function(e,n){t.callbacks[u.invocationId]=function(t,r){r?n(r):t&&(t.type===o.Completion?t.error?n(new Error(t.error)):e(t.result):n(new Error("Unexpected message type: "+t.type)))};var r=t.sendWithProtocol(u).catch(function(e){n(e),delete t.callbacks[u.invocationId]});t.launchStreams(s,r)})},e.prototype.on=function(e,t){e&&t&&(e=e.toLowerCase(),this.methods[e]||(this.methods[e]=[]),-1===this.methods[e].indexOf(t)&&this.methods[e].push(t))},e.prototype.off=function(e,t){if(e){e=e.toLowerCase();var n=this.methods[e];if(n)if(t){var r=n.indexOf(t);-1!==r&&(n.splice(r,1),0===n.length&&delete this.methods[e])}else delete this.methods[e]}},e.prototype.onclose=function(e){e&&this.closedCallbacks.push(e)},e.prototype.onreconnecting=function(e){e&&this.reconnectingCallbacks.push(e)},e.prototype.onreconnected=function(e){e&&this.reconnectedCallbacks.push(e)},e.prototype.processIncomingData=function(e){if(this.cleanupTimeout(),this.receivedHandshakeResponse||(e=this.processHandshakeResponse(e),this.receivedHandshakeResponse=!0),e)for(var t=0,n=this.protocol.parseMessages(e,this.logger);t<n.length;t++){var r=n[t];switch(r.type){case o.Invocation:this.invokeClientMethod(r);break;case o.StreamItem:case o.Completion:var i=this.callbacks[r.invocationId];i&&(r.type===o.Completion&&delete this.callbacks[r.invocationId],i(r));break;case o.Ping:break;case o.Close:this.logger.log(u.a.Information,"Close message received from server.");var s=r.error?new Error("Server returned an error on close: "+r.error):void 0;!0===r.allowReconnect?this.connection.stop(s):this.stopPromise=this.stopInternal(s);break;default:this.logger.log(u.a.Warning,"Invalid message type: "+r.type+".")}}this.resetTimeoutPeriod()},e.prototype.processHandshakeResponse=function(e){var t,n,r;try{r=(t=this.handshakeProtocol.parseHandshakeResponse(e))[0],n=t[1]}catch(e){var o="Error parsing handshake response: "+e;this.logger.log(u.a.Error,o);var i=new Error(o);throw this.handshakeRejecter(i),i}if(n.error){o="Server returned handshake error: "+n.error;this.logger.log(u.a.Error,o);i=new Error(o);throw this.handshakeRejecter(i),i}return this.logger.log(u.a.Debug,"Server handshake complete."),this.handshakeResolver(),r},e.prototype.resetKeepAliveInterval=function(){var e=this;this.cleanupPingTimer(),this.pingServerHandle=setTimeout(function(){return v(e,void 0,void 0,function(){return b(this,function(e){switch(e.label){case 0:if(this.connectionState!==d.Connected)return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,this.sendMessage(this.cachedPingMessage)];case 2:return e.sent(),[3,4];case 3:return e.sent(),this.cleanupPingTimer(),[3,4];case 4:return[2]}})})},this.keepAliveIntervalInMilliseconds)},e.prototype.resetTimeoutPeriod=function(){var e=this;this.connection.features&&this.connection.features.inherentKeepAlive||(this.timeoutHandle=setTimeout(function(){return e.serverTimeout()},this.serverTimeoutInMilliseconds))},e.prototype.serverTimeout=function(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))},e.prototype.invokeClientMethod=function(e){var t=this,n=this.methods[e.target.toLowerCase()];if(n){try{n.forEach(function(n){return n.apply(t,e.arguments)})}catch(t){this.logger.log(u.a.Error,"A callback for the method "+e.target.toLowerCase()+" threw error '"+t+"'.")}if(e.invocationId){var r="Server requested a response, which is not supported in this version of the client.";this.logger.log(u.a.Error,r),this.stopPromise=this.stopInternal(new Error(r))}}else this.logger.log(u.a.Warning,"No client method with the name '"+e.target+"' found.")},e.prototype.connectionClosed=function(e){this.logger.log(u.a.Debug,"HubConnection.connectionClosed("+e+") called while in state "+this.connectionState+"."),this.stopDuringStartError=this.stopDuringStartError||e||new Error("The underlying connection was closed before the hub handshake could complete."),this.handshakeResolver&&this.handshakeResolver(),this.cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this.cleanupTimeout(),this.cleanupPingTimer(),this.connectionState===d.Disconnecting?this.completeClose(e):this.connectionState===d.Connected&&this.reconnectPolicy?this.reconnect(e):this.connectionState===d.Connected&&this.completeClose(e)},e.prototype.completeClose=function(e){var t=this;if(this.connectionStarted){this.connectionState=d.Disconnected,this.connectionStarted=!1;try{this.closedCallbacks.forEach(function(n){return n.apply(t,[e])})}catch(t){this.logger.log(u.a.Error,"An onclose callback called with error '"+e+"' threw error '"+t+"'.")}}},e.prototype.reconnect=function(e){return v(this,void 0,void 0,function(){var t,n,r,o,i,s=this;return b(this,function(a){switch(a.label){case 0:if(t=Date.now(),n=0,r=void 0!==e?e:new Error("Attempting to reconnect due to a unknown error."),null===(o=this.getNextRetryDelay(n++,0,r)))return this.logger.log(u.a.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),this.completeClose(e),[2];if(this.connectionState=d.Reconnecting,e?this.logger.log(u.a.Information,"Connection reconnecting because of error '"+e+"'."):this.logger.log(u.a.Information,"Connection reconnecting."),this.onreconnecting){try{this.reconnectingCallbacks.forEach(function(t){return t.apply(s,[e])})}catch(t){this.logger.log(u.a.Error,"An onreconnecting callback called with error '"+e+"' threw error '"+t+"'.")}if(this.connectionState!==d.Reconnecting)return this.logger.log(u.a.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting."),[2]}a.label=1;case 1:return null===o?[3,7]:(this.logger.log(u.a.Information,"Reconnect attempt number "+n+" will start in "+o+" ms."),[4,new Promise(function(e){s.reconnectDelayHandle=setTimeout(e,o)})]);case 2:if(a.sent(),this.reconnectDelayHandle=void 0,this.connectionState!==d.Reconnecting)return this.logger.log(u.a.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting."),[2];a.label=3;case 3:return a.trys.push([3,5,,6]),[4,this.startInternal()];case 4:if(a.sent(),this.connectionState=d.Connected,this.logger.log(u.a.Information,"HubConnection reconnected successfully."),this.onreconnected)try{this.reconnectedCallbacks.forEach(function(e){return e.apply(s,[s.connection.connectionId])})}catch(e){this.logger.log(u.a.Error,"An onreconnected callback called with connectionId '"+this.connection.connectionId+"; threw error '"+e+"'.")}return[2];case 5:return i=a.sent(),this.logger.log(u.a.Information,"Reconnect attempt failed because of error '"+i+"'."),this.connectionState!==d.Reconnecting?(this.logger.log(u.a.Debug,"Connection left the reconnecting state during reconnect attempt. Done reconnecting."),[2]):(r=i instanceof Error?i:new Error(i.toString()),o=this.getNextRetryDelay(n++,Date.now()-t,r),[3,6]);case 6:return[3,1];case 7:return this.logger.log(u.a.Information,"Reconnect retries have been exhausted after "+(Date.now()-t)+" ms and "+n+" failed attempts. Connection disconnecting."),this.completeClose(),[2]}})})},e.prototype.getNextRetryDelay=function(e,t,n){try{return this.reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:t,previousRetryCount:e,retryReason:n})}catch(n){return this.logger.log(u.a.Error,"IRetryPolicy.nextRetryDelayInMilliseconds("+e+", "+t+") threw error '"+n+"'."),null}},e.prototype.cancelCallbacksWithError=function(e){var t=this.callbacks;this.callbacks={},Object.keys(t).forEach(function(n){(0,t[n])(null,e)})},e.prototype.cleanupPingTimer=function(){this.pingServerHandle&&clearTimeout(this.pingServerHandle)},e.prototype.cleanupTimeout=function(){this.timeoutHandle&&clearTimeout(this.timeoutHandle)},e.prototype.createInvocation=function(e,t,n,r){if(n)return{arguments:t,streamIds:r,target:e,type:o.Invocation};var i=this.invocationId;return this.invocationId++,{arguments:t,invocationId:i.toString(),streamIds:r,target:e,type:o.Invocation}},e.prototype.launchStreams=function(e,t){var n=this;if(0!==e.length){t||(t=Promise.resolve());var r=function(r){e[r].subscribe({complete:function(){t=t.then(function(){return n.sendWithProtocol(n.createCompletionMessage(r))})},error:function(e){var o;o=e instanceof Error?e.message:e&&e.toString?e.toString():"Unknown error",t=t.then(function(){return n.sendWithProtocol(n.createCompletionMessage(r,o))})},next:function(e){t=t.then(function(){return n.sendWithProtocol(n.createStreamItemMessage(r,e))})}})};for(var o in e)r(o)}},e.prototype.replaceStreamingParams=function(e){for(var t=[],n=[],r=0;r<e.length;r++){var o=e[r];if(this.isObservable(o)){var i=this.invocationId;this.invocationId++,t[i]=o,n.push(i.toString()),e.splice(r,1)}}return[t,n]},e.prototype.isObservable=function(e){return e&&e.subscribe&&"function"==typeof e.subscribe},e.prototype.createStreamInvocation=function(e,t,n){var r=this.invocationId;return this.invocationId++,{arguments:t,invocationId:r.toString(),streamIds:n,target:e,type:o.StreamInvocation}},e.prototype.createCancelInvocation=function(e){return{invocationId:e,type:o.CancelInvocation}},e.prototype.createStreamItemMessage=function(e,t){return{invocationId:e,item:t,type:o.StreamItem}},e.prototype.createCompletionMessage=function(e,t,n){return t?{error:t,invocationId:e,type:o.Completion}:{invocationId:e,result:n,type:o.Completion}},e}(),T=[0,2e3,1e4,3e4,null],C=function(){function e(e){this.retryDelays=void 0!==e?e.concat([null]):T}return e.prototype.nextRetryDelayInMilliseconds=function(e){return this.retryDelays[e.previousRetryCount]},e}();!function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(E||(E={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(S||(S={}));var I=function(){function e(){this.isAborted=!1,this.onabort=null}return e.prototype.abort=function(){this.isAborted||(this.isAborted=!0,this.onabort&&this.onabort())},Object.defineProperty(e.prototype,"signal",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"aborted",{get:function(){return this.isAborted},enumerable:!0,configurable:!0}),e}(),k=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},P=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},R=function(){function e(e,t,n,r){this.httpClient=e,this.accessTokenFactory=t,this.logger=n,this.pollAbort=new I,this.logMessageContent=r,this.running=!1,this.onreceive=null,this.onclose=null}return Object.defineProperty(e.prototype,"pollAborted",{get:function(){return this.pollAbort.aborted},enumerable:!0,configurable:!0}),e.prototype.connect=function(e,t){return k(this,void 0,void 0,function(){var n,r,o,s;return P(this,function(a){switch(a.label){case 0:if(g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.url=e,this.logger.log(u.a.Trace,"(LongPolling transport) Connecting."),t===S.Binary&&"undefined"!=typeof XMLHttpRequest&&"string"!=typeof(new XMLHttpRequest).responseType)throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");return n={abortSignal:this.pollAbort.signal,headers:{},timeout:1e5},t===S.Binary&&(n.responseType="arraybuffer"),[4,this.getAccessToken()];case 1:return r=a.sent(),this.updateHeaderToken(n,r),o=e+"&_="+Date.now(),this.logger.log(u.a.Trace,"(LongPolling transport) polling: "+o+"."),[4,this.httpClient.get(o,n)];case 2:return 200!==(s=a.sent()).statusCode?(this.logger.log(u.a.Error,"(LongPolling transport) Unexpected response code: "+s.statusCode+"."),this.closeError=new i.b(s.statusText||"",s.statusCode),this.running=!1):this.running=!0,this.receiving=this.poll(this.url,n),[2]}})})},e.prototype.getAccessToken=function(){return k(this,void 0,void 0,function(){return P(this,function(e){switch(e.label){case 0:return this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:return[2,e.sent()];case 2:return[2,null]}})})},e.prototype.updateHeaderToken=function(e,t){e.headers||(e.headers={}),t?e.headers.Authorization="Bearer "+t:e.headers.Authorization&&delete e.headers.Authorization},e.prototype.poll=function(e,t){return k(this,void 0,void 0,function(){var n,r,o,s;return P(this,function(a){switch(a.label){case 0:a.trys.push([0,,8,9]),a.label=1;case 1:return this.running?[4,this.getAccessToken()]:[3,7];case 2:n=a.sent(),this.updateHeaderToken(t,n),a.label=3;case 3:return a.trys.push([3,5,,6]),r=e+"&_="+Date.now(),this.logger.log(u.a.Trace,"(LongPolling transport) polling: "+r+"."),[4,this.httpClient.get(r,t)];case 4:return 204===(o=a.sent()).statusCode?(this.logger.log(u.a.Information,"(LongPolling transport) Poll terminated by server."),this.running=!1):200!==o.statusCode?(this.logger.log(u.a.Error,"(LongPolling transport) Unexpected response code: "+o.statusCode+"."),this.closeError=new i.b(o.statusText||"",o.statusCode),this.running=!1):o.content?(this.logger.log(u.a.Trace,"(LongPolling transport) data received. "+Object(g.f)(o.content,this.logMessageContent)+"."),this.onreceive&&this.onreceive(o.content)):this.logger.log(u.a.Trace,"(LongPolling transport) Poll timed out, reissuing."),[3,6];case 5:return s=a.sent(),this.running?s instanceof i.c?this.logger.log(u.a.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this.closeError=s,this.running=!1):this.logger.log(u.a.Trace,"(LongPolling transport) Poll errored after shutdown: "+s.message),[3,6];case 6:return[3,1];case 7:return[3,9];case 8:return this.logger.log(u.a.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this.raiseOnClose(),[7];case 9:return[2]}})})},e.prototype.send=function(e){return k(this,void 0,void 0,function(){return P(this,function(t){return this.running?[2,Object(g.h)(this.logger,"LongPolling",this.httpClient,this.url,this.accessTokenFactory,e,this.logMessageContent)]:[2,Promise.reject(new Error("Cannot send until the transport is connected"))]})})},e.prototype.stop=function(){return k(this,void 0,void 0,function(){var e,t;return P(this,function(n){switch(n.label){case 0:this.logger.log(u.a.Trace,"(LongPolling transport) Stopping polling."),this.running=!1,this.pollAbort.abort(),n.label=1;case 1:return n.trys.push([1,,5,6]),[4,this.receiving];case 2:return n.sent(),this.logger.log(u.a.Trace,"(LongPolling transport) sending DELETE request to "+this.url+"."),e={headers:{}},[4,this.getAccessToken()];case 3:return t=n.sent(),this.updateHeaderToken(e,t),[4,this.httpClient.delete(this.url,e)];case 4:return n.sent(),this.logger.log(u.a.Trace,"(LongPolling transport) DELETE request sent."),[3,6];case 5:return this.logger.log(u.a.Trace,"(LongPolling transport) Stop finished."),this.raiseOnClose(),[7];case 6:return[2]}})})},e.prototype.raiseOnClose=function(){if(this.onclose){var e="(LongPolling transport) Firing onclose event.";this.closeError&&(e+=" Error: "+this.closeError),this.logger.log(u.a.Trace,e),this.onclose(this.closeError)}},e}(),x=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},A=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},D=function(){function e(e,t,n,r,o){this.httpClient=e,this.accessTokenFactory=t,this.logger=n,this.logMessageContent=r,this.eventSourceConstructor=o,this.onreceive=null,this.onclose=null}return e.prototype.connect=function(e,t){return x(this,void 0,void 0,function(){var n,r=this;return A(this,function(o){switch(o.label){case 0:return g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.logger.log(u.a.Trace,"(SSE transport) Connecting."),this.url=e,this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(n=o.sent())&&(e+=(e.indexOf("?")<0?"?":"&")+"access_token="+encodeURIComponent(n)),o.label=2;case 2:return[2,new Promise(function(n,o){var i=!1;if(t===S.Text){var s;if(g.c.isBrowser||g.c.isWebWorker)s=new r.eventSourceConstructor(e,{withCredentials:!0});else{var a=r.httpClient.getCookieString(e);s=new r.eventSourceConstructor(e,{withCredentials:!0,headers:{Cookie:a}})}try{s.onmessage=function(e){if(r.onreceive)try{r.logger.log(u.a.Trace,"(SSE transport) data received. "+Object(g.f)(e.data,r.logMessageContent)+"."),r.onreceive(e.data)}catch(e){return void r.close(e)}},s.onerror=function(e){var t=new Error(e.data||"Error occurred");i?r.close(t):o(t)},s.onopen=function(){r.logger.log(u.a.Information,"SSE connected to "+r.url),r.eventSource=s,i=!0,n()}}catch(e){return void o(e)}}else o(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"))})]}})})},e.prototype.send=function(e){return x(this,void 0,void 0,function(){return A(this,function(t){return this.eventSource?[2,Object(g.h)(this.logger,"SSE",this.httpClient,this.url,this.accessTokenFactory,e,this.logMessageContent)]:[2,Promise.reject(new Error("Cannot send until the transport is connected"))]})})},e.prototype.stop=function(){return this.close(),Promise.resolve()},e.prototype.close=function(e){this.eventSource&&(this.eventSource.close(),this.eventSource=void 0,this.onclose&&this.onclose(e))},e}(),O=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},L=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},M=function(){function e(e,t,n,r,o){this.logger=n,this.accessTokenFactory=t,this.logMessageContent=r,this.webSocketConstructor=o,this.httpClient=e,this.onreceive=null,this.onclose=null}return e.prototype.connect=function(e,t){return O(this,void 0,void 0,function(){var n,r=this;return L(this,function(o){switch(o.label){case 0:return g.a.isRequired(e,"url"),g.a.isRequired(t,"transferFormat"),g.a.isIn(t,S,"transferFormat"),this.logger.log(u.a.Trace,"(WebSockets transport) Connecting."),this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(n=o.sent())&&(e+=(e.indexOf("?")<0?"?":"&")+"access_token="+encodeURIComponent(n)),o.label=2;case 2:return[2,new Promise(function(n,o){var i;e=e.replace(/^http/,"ws");var s=r.httpClient.getCookieString(e),a=!1;g.c.isNode&&s&&(i=new r.webSocketConstructor(e,void 0,{headers:{Cookie:""+s}})),i||(i=new r.webSocketConstructor(e)),t===S.Binary&&(i.binaryType="arraybuffer"),i.onopen=function(t){r.logger.log(u.a.Information,"WebSocket connected to "+e+"."),r.webSocket=i,a=!0,n()},i.onerror=function(e){var t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:new Error("There was an error with the transport."),o(t)},i.onmessage=function(e){r.logger.log(u.a.Trace,"(WebSockets transport) data received. "+Object(g.f)(e.data,r.logMessageContent)+"."),r.onreceive&&r.onreceive(e.data)},i.onclose=function(e){if(a)r.close(e);else{var t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:new Error("There was an error with the transport."),o(t)}}})]}})})},e.prototype.send=function(e){return this.webSocket&&this.webSocket.readyState===this.webSocketConstructor.OPEN?(this.logger.log(u.a.Trace,"(WebSockets transport) sending data. "+Object(g.f)(e,this.logMessageContent)+"."),this.webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")},e.prototype.stop=function(){return this.webSocket&&(this.webSocket.onclose=function(){},this.webSocket.onmessage=function(){},this.webSocket.onerror=function(){},this.webSocket.close(),this.webSocket=void 0,this.close(void 0)),Promise.resolve()},e.prototype.close=function(e){this.logger.log(u.a.Trace,"(WebSockets transport) socket closed."),this.onclose&&(!e||!1!==e.wasClean&&1e3===e.code?this.onclose():this.onclose(new Error("WebSocket closed with status code: "+e.code+" ("+e.reason+").")))},e}(),B=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},U=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},j=null,N=null;if(g.c.isNode){var F=require;j=F("ws"),N=F("eventsource")}var H=function(){function e(e,t){void 0===t&&(t={}),this.features={},this.negotiateVersion=1,g.a.isRequired(e,"url"),this.logger=Object(g.e)(t.logger),this.baseUrl=this.resolveUrl(e),(t=t||{}).logMessageContent=t.logMessageContent||!1,g.c.isNode||"undefined"==typeof WebSocket||t.WebSocket?g.c.isNode&&!t.WebSocket&&j&&(t.WebSocket=j):t.WebSocket=WebSocket,g.c.isNode||"undefined"==typeof EventSource||t.EventSource?g.c.isNode&&!t.EventSource&&void 0!==N&&(t.EventSource=N):t.EventSource=EventSource,this.httpClient=t.httpClient||new h(this.logger),this.connectionState="Disconnected",this.connectionStarted=!1,this.options=t,this.onreceive=null,this.onclose=null}return e.prototype.start=function(e){return B(this,void 0,void 0,function(){var t;return U(this,function(n){switch(n.label){case 0:return e=e||S.Binary,g.a.isIn(e,S,"transferFormat"),this.logger.log(u.a.Debug,"Starting connection with transfer format '"+S[e]+"'."),"Disconnected"!==this.connectionState?[2,Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."))]:(this.connectionState="Connecting ",this.startInternalPromise=this.startInternal(e),[4,this.startInternalPromise]);case 1:return n.sent(),"Disconnecting"!==this.connectionState?[3,3]:(t="Failed to start the HttpConnection before stop() was called.",this.logger.log(u.a.Error,t),[4,this.stopPromise]);case 2:return n.sent(),[2,Promise.reject(new Error(t))];case 3:if("Connected"!==this.connectionState)return t="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!",this.logger.log(u.a.Error,t),[2,Promise.reject(new Error(t))];n.label=4;case 4:return this.connectionStarted=!0,[2]}})})},e.prototype.send=function(e){return"Connected"!==this.connectionState?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this.sendQueue||(this.sendQueue=new q(this.transport)),this.sendQueue.send(e))},e.prototype.stop=function(e){return B(this,void 0,void 0,function(){var t=this;return U(this,function(n){switch(n.label){case 0:return"Disconnected"===this.connectionState?(this.logger.log(u.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnected state."),[2,Promise.resolve()]):"Disconnecting"===this.connectionState?(this.logger.log(u.a.Debug,"Call to HttpConnection.stop("+e+") ignored because the connection is already in the disconnecting state."),[2,this.stopPromise]):(this.connectionState="Disconnecting",this.stopPromise=new Promise(function(e){t.stopPromiseResolver=e}),[4,this.stopInternal(e)]);case 1:return n.sent(),[4,this.stopPromise];case 2:return n.sent(),[2]}})})},e.prototype.stopInternal=function(e){return B(this,void 0,void 0,function(){var t,n;return U(this,function(r){switch(r.label){case 0:this.stopError=e,r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.startInternalPromise];case 2:return r.sent(),[3,4];case 3:return r.sent(),[3,4];case 4:if(!this.sendQueue)return[3,9];r.label=5;case 5:return r.trys.push([5,7,,8]),[4,this.sendQueue.stop()];case 6:return r.sent(),[3,8];case 7:return t=r.sent(),this.logger.log(u.a.Error,"TransportSendQueue.stop() threw error '"+t+"'."),[3,8];case 8:this.sendQueue=void 0,r.label=9;case 9:if(!this.transport)return[3,14];r.label=10;case 10:return r.trys.push([10,12,,13]),[4,this.transport.stop()];case 11:return r.sent(),[3,13];case 12:return n=r.sent(),this.logger.log(u.a.Error,"HttpConnection.transport.stop() threw error '"+n+"'."),this.stopConnection(),[3,13];case 13:return this.transport=void 0,[3,15];case 14:this.logger.log(u.a.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed."),this.stopConnection(),r.label=15;case 15:return[2]}})})},e.prototype.startInternal=function(e){return B(this,void 0,void 0,function(){var t,n,r,o,i,s;return U(this,function(a){switch(a.label){case 0:t=this.baseUrl,this.accessTokenFactory=this.options.accessTokenFactory,a.label=1;case 1:return a.trys.push([1,12,,13]),this.options.skipNegotiation?this.options.transport!==E.WebSockets?[3,3]:(this.transport=this.constructTransport(E.WebSockets),[4,this.startTransport(t,e)]):[3,5];case 2:return a.sent(),[3,4];case 3:throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");case 4:return[3,11];case 5:n=null,r=0,o=function(){var e;return U(this,function(o){switch(o.label){case 0:return[4,i.getNegotiationResponse(t)];case 1:if(n=o.sent(),"Disconnecting"===i.connectionState||"Disconnected"===i.connectionState)throw new Error("The connection was stopped during negotiation.");if(n.error)throw new Error(n.error);if(n.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");return n.url&&(t=n.url),n.accessToken&&(e=n.accessToken,i.accessTokenFactory=function(){return e}),r++,[2]}})},i=this,a.label=6;case 6:return[5,o()];case 7:a.sent(),a.label=8;case 8:if(n.url&&r<100)return[3,6];a.label=9;case 9:if(100===r&&n.url)throw new Error("Negotiate redirection limit exceeded.");return[4,this.createTransport(t,this.options.transport,n,e)];case 10:a.sent(),a.label=11;case 11:return this.transport instanceof R&&(this.features.inherentKeepAlive=!0),"Connecting "===this.connectionState&&(this.logger.log(u.a.Debug,"The HttpConnection connected successfully."),this.connectionState="Connected"),[3,13];case 12:return s=a.sent(),this.logger.log(u.a.Error,"Failed to start the connection: "+s),this.connectionState="Disconnected",this.transport=void 0,[2,Promise.reject(s)];case 13:return[2]}})})},e.prototype.getNegotiationResponse=function(e){return B(this,void 0,void 0,function(){var t,n,r,o,i,s,a;return U(this,function(c){switch(c.label){case 0:return this.accessTokenFactory?[4,this.accessTokenFactory()]:[3,2];case 1:(r=c.sent())&&((t={}).Authorization="Bearer "+r,n=t),c.label=2;case 2:o=this.resolveNegotiateUrl(e),this.logger.log(u.a.Debug,"Sending negotiation request: "+o+"."),c.label=3;case 3:return c.trys.push([3,5,,6]),[4,this.httpClient.post(o,{content:"",headers:n})];case 4:return 200!==(i=c.sent()).statusCode?[2,Promise.reject(new Error("Unexpected status code returned from negotiate "+i.statusCode))]:((!(s=JSON.parse(i.content)).negotiateVersion||s.negotiateVersion<1)&&(s.connectionToken=s.connectionId),[2,s]);case 5:return a=c.sent(),this.logger.log(u.a.Error,"Failed to complete negotiation with the server: "+a),[2,Promise.reject(a)];case 6:return[2]}})})},e.prototype.createConnectUrl=function(e,t){return t?e+(-1===e.indexOf("?")?"?":"&")+"id="+t:e},e.prototype.createTransport=function(e,t,n,r){return B(this,void 0,void 0,function(){var o,i,s,a,c,l,f,h,p,d,g;return U(this,function(y){switch(y.label){case 0:return o=this.createConnectUrl(e,n.connectionToken),this.isITransport(t)?(this.logger.log(u.a.Debug,"Connection was provided an instance of ITransport, using that directly."),this.transport=t,[4,this.startTransport(o,r)]):[3,2];case 1:return y.sent(),this.connectionId=n.connectionId,[2];case 2:i=[],s=n.availableTransports||[],a=n,c=0,l=s,y.label=3;case 3:return c<l.length?(f=l[c],(h=this.resolveTransportOrError(f,t,r))instanceof Error?(i.push(f.transport+" failed: "+h),[3,12]):[3,4]):[3,13];case 4:if(!this.isITransport(h))return[3,12];if(this.transport=h,a)return[3,9];y.label=5;case 5:return y.trys.push([5,7,,8]),[4,this.getNegotiationResponse(e)];case 6:return a=y.sent(),[3,8];case 7:return p=y.sent(),[2,Promise.reject(p)];case 8:o=this.createConnectUrl(e,a.connectionToken),y.label=9;case 9:return y.trys.push([9,11,,12]),[4,this.startTransport(o,r)];case 10:return y.sent(),this.connectionId=a.connectionId,[2];case 11:return d=y.sent(),this.logger.log(u.a.Error,"Failed to start the transport '"+f.transport+"': "+d),a=void 0,i.push(f.transport+" failed: "+d),"Connecting "!==this.connectionState?(g="Failed to select transport before stop() was called.",this.logger.log(u.a.Debug,g),[2,Promise.reject(new Error(g))]):[3,12];case 12:return c++,[3,3];case 13:return i.length>0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}})})},e.prototype.constructTransport=function(e){switch(e){case E.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new M(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket);case E.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new D(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource);case E.LongPolling:return new R(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1);default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=E[e.transport];if(null==r)return this.logger.log(u.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it was disabled by the client."),new Error("'"+E[r]+"' is disabled by the client.");if(!(e.transferFormats.map(function(e){return S[e]}).indexOf(n)>=0))return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it does not support the requested transfer format '"+S[n]+"'."),new Error("'"+E[r]+"' does not support "+S[n]+".");if(r===E.WebSockets&&!this.options.WebSocket||r===E.ServerSentEvents&&!this.options.EventSource)return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it is not supported in your environment.'"),new Error("'"+E[r]+"' is not supported in your environment.");this.logger.log(u.a.Debug,"Selecting transport '"+E[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){if(this.logger.log(u.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState)if("Connecting "!==this.connectionState){if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(u.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(u.a.Information,"Connection disconnected."),this.connectionId=void 0,this.connectionState="Disconnected",this.onclose&&this.connectionStarted){this.connectionStarted=!1;try{this.onclose(e)}catch(t){this.logger.log(u.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(u.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection hasn't yet left the in the connecting state.");else this.logger.log(u.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!g.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(u.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var q=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new Y,this.transportResult=new Y,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new Y),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return B(this,void 0,void 0,function(){var t,n,r;return U(this,function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new Y,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}})})},e.concatBuffers=function(e){for(var t=e.map(function(e){return e.byteLength}).reduce(function(e,t){return e+t}),n=new Uint8Array(t),r=0,o=0,i=e;o<i.length;o++){var s=i[o];n.set(new Uint8Array(s),r),r+=s.byteLength}return n},e}(),Y=function(){function e(){var e=this;this.promise=new Promise(function(t,n){var r;return r=[t,n],e.resolver=r[0],e.rejecter=r[1],r})}return e.prototype.resolve=function(){this.resolver()},e.prototype.reject=function(e){this.rejecter(e)},e}(),W=n(6),z=n(7),J="json",V=function(){function e(){this.name=J,this.version=1,this.transferFormat=S.Text}return e.prototype.parseMessages=function(e,t){if("string"!=typeof e)throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];null===t&&(t=W.a.instance);for(var n=[],r=0,i=z.a.parse(e);r<i.length;r++){var s=i[r],a=JSON.parse(s);if("number"!=typeof a.type)throw new Error("Invalid payload.");switch(a.type){case o.Invocation:this.isInvocationMessage(a);break;case o.StreamItem:this.isStreamItemMessage(a);break;case o.Completion:this.isCompletionMessage(a);break;case o.Ping:case o.Close:break;default:t.log(u.a.Information,"Unknown message type '"+a.type+"' ignored.");continue}n.push(a)}return n},e.prototype.writeMessage=function(e){return z.a.write(JSON.stringify(e))},e.prototype.isInvocationMessage=function(e){this.assertNotEmptyString(e.target,"Invalid payload for Invocation message."),void 0!==e.invocationId&&this.assertNotEmptyString(e.invocationId,"Invalid payload for Invocation message.")},e.prototype.isStreamItemMessage=function(e){if(this.assertNotEmptyString(e.invocationId,"Invalid payload for StreamItem message."),void 0===e.item)throw new Error("Invalid payload for StreamItem message.")},e.prototype.isCompletionMessage=function(e){if(e.result&&e.error)throw new Error("Invalid payload for Completion message.");!e.result&&e.error&&this.assertNotEmptyString(e.error,"Invalid payload for Completion message."),this.assertNotEmptyString(e.invocationId,"Invalid payload for Completion message.")},e.prototype.assertNotEmptyString=function(e,t){if("string"!=typeof e||""===e)throw new Error(t)},e}(),K=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},X={trace:u.a.Trace,debug:u.a.Debug,info:u.a.Information,information:u.a.Information,warn:u.a.Warning,warning:u.a.Warning,error:u.a.Error,critical:u.a.Critical,none:u.a.None};var G=function(){function e(){}return e.prototype.configureLogging=function(e){if(g.a.isRequired(e,"logging"),void 0!==e.log)this.logger=e;else if("string"==typeof e){var t=function(e){var t=X[e.toLowerCase()];if(void 0!==t)return t;throw new Error("Unknown log level: "+e)}(e);this.logger=new g.b(t)}else this.logger=new g.b(e);return this},e.prototype.withUrl=function(e,t){return g.a.isRequired(e,"url"),this.url=e,this.httpConnectionOptions=K({},this.httpConnectionOptions,"object"==typeof t?t:{transport:t}),this},e.prototype.withHubProtocol=function(e){return g.a.isRequired(e,"protocol"),this.protocol=e,this},e.prototype.withAutomaticReconnect=function(e){if(this.reconnectPolicy)throw new Error("A reconnectPolicy has already been set.");return e?Array.isArray(e)?this.reconnectPolicy=new C(e):this.reconnectPolicy=e:this.reconnectPolicy=new C,this},e.prototype.build=function(){var e=this.httpConnectionOptions||{};if(void 0===e.logger&&(e.logger=this.logger),!this.url)throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");var t=new H(this.url,e);return _.create(t,this.logger||W.a.instance,this.protocol||new V,this.reconnectPolicy)},e}();n.d(t,"VERSION",function(){return Q}),n.d(t,"AbortError",function(){return i.a}),n.d(t,"HttpError",function(){return i.b}),n.d(t,"TimeoutError",function(){return i.c}),n.d(t,"HttpClient",function(){return s.a}),n.d(t,"HttpResponse",function(){return s.b}),n.d(t,"DefaultHttpClient",function(){return h}),n.d(t,"HubConnection",function(){return _}),n.d(t,"HubConnectionState",function(){return d}),n.d(t,"HubConnectionBuilder",function(){return G}),n.d(t,"MessageType",function(){return o}),n.d(t,"LogLevel",function(){return u.a}),n.d(t,"HttpTransportType",function(){return E}),n.d(t,"TransferFormat",function(){return S}),n.d(t,"NullLogger",function(){return W.a}),n.d(t,"JsonHubProtocol",function(){return V}),n.d(t,"Subject",function(){return y});var Q="0.0.0-DEV_BUILD"},function(e,t,n){"use strict";n.d(t,"b",function(){return i}),n.d(t,"c",function(){return s}),n.d(t,"a",function(){return a});var r,o=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return o(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),a=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error)},function(e,t,n){"use strict";n.d(t,"b",function(){return o}),n.d(t,"a",function(){return i});var r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},o=function(){return function(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}(),i=function(){function e(){}return e.prototype.get=function(e,t){return this.send(r({},t,{method:"GET",url:e}))},e.prototype.post=function(e,t){return this.send(r({},t,{method:"POST",url:e}))},e.prototype.delete=function(e,t){return this.send(r({},t,{method:"DELETE",url:e}))},e.prototype.getCookieString=function(e){return""},e}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(17);var r=n(26),o=n(11),i={},s=!1;function a(e,t,n){var o=i[e];o||(o=i[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=a,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");a(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=i[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),a=r.values(o),u=r.count(o),c=t.referenceFrames(),l=r.values(c),f=t.diffReader,h=0;h<u;h++){var p=t.updatedComponentsEntry(a,h),d=f.componentId(p),g=f.edits(p);n.updateComponent(t,d,g,l)}var y=t.disposedComponentIds(),v=r.values(y),b=r.count(y);for(h=0;h<b;h++)d=t.disposedComponentIdsEntry(v,h),n.disposeComponent(d);var m=t.disposedEventHandlerIds(),w=r.values(m),E=r.count(m);for(h=0;h<E;h++){var S=t.disposedEventHandlerIdsEntry(w,h);n.disposeEventHandler(S)}s&&(s=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){s=!0}},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}()},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.write=function(t){return""+t+e.RecordSeparator},e.parse=function(t){if(t[t.length-1]!==e.RecordSeparator)throw new Error("Message is incomplete.");var n=t.split(e.RecordSeparator);return n.pop(),n},e.RecordSeparatorCode=30,e.RecordSeparator=String.fromCharCode(e.RecordSeparatorCode),e}()},function(e,t,n){"use strict";var r=n(22),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(19);i.inherits=n(14);var s=n(38),a=n(43);i.inherits(f,s);for(var u=o(a.prototype),c=0;c<u.length;c++){var l=u[c];f.prototype[l]||(f.prototype[l]=a.prototype[l])}function f(e){if(!(this instanceof f))return new f(e);s.call(this,e),a.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",h)}function h(){this.allowHalfOpen||this._writableState.ended||r.nextTick(p,this)}function p(e){e.end()}Object.defineProperty(f.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(f.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),f.prototype._destroy=function(e,t){this.push(null),this.end(),r.nextTick(t,e)}},function(e,t,n){"use strict";var r=n(13).Buffer,o=n(58),i=n(21),s=n(71),a=n(74),u=n(75);e.exports=function(e){var t=[],n=[];return{encode:u(t,(e=e||{forceFloat64:!1,compatibilityMode:!1,disableTimestampEncoding:!1}).forceFloat64,e.compatibilityMode,e.disableTimestampEncoding),decode:a(n),register:function(e,t,n,s){return o(t,"must have a constructor"),o(n,"must have an encode function"),o(e>=0,"must have a non-negative type"),o(s,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),s=r.allocUnsafe(1);return s.writeInt8(e,0),o.append(s),o.append(n(t)),o}),this.registerDecoder(e,s),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:s.encoder,decoder:s.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:a.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(16);var i,s=n(5),a=!1,u=!1,c=null;function l(e,t){var n=p(e);if(!t&&d(n))f(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function f(e,t){s.resetScrollAfterNextBatch(),history.pushState(null,"",e),h(t)}function h(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return c?[4,c(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(i=i||document.createElement("a")).href=e,i.href}function d(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(c=e,u)return;u=!0,window.addEventListener("popstate",function(){return h(!1)})},enableNavigationInterception:function(){a=!0},navigateTo:l,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(a&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));d(r)&&(e.preventDefault(),f(r,!0))}}})},t.navigateTo=l},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),i=p("_blazorLogicalEnd");function s(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function a(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var s=c(t);if(n<s.length){var a=s[n];a.parentNode.insertBefore(e,a),s.splice(n,0,i)}else h(e,t),s.push(i);i[o]=t,r in i||(i[r]=[])}function u(e){return e[o]||null}function c(e){return e[r]}function l(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function f(e){var t=c(u(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function h(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=f(t);n?n.parentNode.insertBefore(e,n):h(e,u(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=s(n,!0),a=c(r);return Array.from(n.childNodes).forEach(function(e){return a.push(e)}),e[o]=r,t&&(e[i]=t,s(t,!0)),s(e,!0)},t.toLogicalElement=s,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return a(n,e,t),n},t.insertLogicalChild=a,t.removeLogicalChild=function e(t,n){var r=c(t).splice(n,1)[0];if(r instanceof Comment)for(var o=c(r);o.length>0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var s=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=s}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(20),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=s),i(o,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function s(e){t.push(e)}function a(e,t,n,r){var o=c();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),s=o.invokeDotNetFromJS(e,t,n,i);return s?f(s):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var s=o++,a=new Promise(function(e,t){n[s]={resolve:e,reject:t}});try{var u=JSON.stringify(i,g);c().beginInvokeDotNetFromJS(s,e,t,r,u)}catch(e){l(s,!1,e)}return a}function c(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=s,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return a(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return u(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,f(t));return null==n?null:JSON.stringify(n,g)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,f(n)))});e&&r.then(function(t){return c().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],g))},function(t){return c().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,h(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);l(parseInt(e),t,r)}};var d=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return a(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return u(null,e,this._id,t)},e.prototype.dispose=function(){u(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function g(e,t){return t instanceof d?t.serializeAsArg():t}s(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new d(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},function(e,t,n){(function(e){function n(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===n(e)},t.isBoolean=function(e){return"boolean"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return"[object RegExp]"===n(e)},t.isObject=function(e){return"object"==typeof e&&null!==e},t.isDate=function(e){return"[object Date]"===n(e)},t.isError=function(e){return"[object Error]"===n(e)||e instanceof Error},t.isFunction=function(e){return"function"==typeof e},t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,n(35).Buffer)},function(e,t,n){"use strict";(function(e){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ -var r=n(50),o=n(51),i=n(52);function a(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()<t)throw new RangeError("Invalid typed array length");return c.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=c.prototype:(null===e&&(e=new c(t)),e.length=t),e}function c(e,t,n){if(!(c.TYPED_ARRAY_SUPPORT||this instanceof c))return new c(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return f(this,e)}return u(this,e,t,n)}function u(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);c.TYPED_ARRAY_SUPPORT?(e=t).__proto__=c.prototype:e=h(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!c.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|d(t,n),o=(e=s(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(c.isBuffer(t)){var n=0|p(t.length);return 0===(e=s(e,n)).length?e:(t.copy(e,0,0,n),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?s(e,0):h(e,t);if("Buffer"===t.type&&i(t.data))return h(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function l(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function f(e,t){if(l(t),e=s(e,t<0?0:0|p(t)),!c.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function h(e,t){var n=t.length<0?0:0|p(t.length);e=s(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function p(e){if(e>=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,c=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,c/=2,n/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;i<s;i++)if(u(e,i)===u(t,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===c)return l*a}else-1!==l&&(i-=i-l),l=-1}else for(n+c>s&&(n=s-c),i=n;i>=0;i--){for(var f=!0,h=0;h<c;h++)if(u(e,i+h)!==u(t,h)){f=!1;break}if(f)return i}return-1}function b(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[n+a]=s}return a}function m(e,t,n,r){return q(F(t,e.length-n),e,n,r)}function w(e,t,n,r){return q(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function E(e,t,n,r){return w(e,t,n,r)}function S(e,t,n,r){return q(H(t),e,n,r)}function C(e,t,n,r){return q(function(e,t){for(var n,r,o,i=[],a=0;a<e.length&&!((t-=2)<0);++a)n=e.charCodeAt(a),r=n>>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function _(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function I(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o<n;){var i,a,s,c,u=e[o],l=null,f=u>239?4:u>223?3:u>191?2:1;if(o+f<=n)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(i=e[o+1]))&&(c=(31&u)<<6|63&i)>127&&(l=c);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(c=(15&u)<<12|(63&i)<<6|63&a)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(c=(15&u)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=T));return n}(r)}t.Buffer=c,t.SlowBuffer=function(e){+e!=e&&(e=0);return c.alloc(+e)},t.INSPECT_MAX_BYTES=50,c.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=a(),c.poolSize=8192,c._augment=function(e){return e.__proto__=c.prototype,e},c.from=function(e,t,n){return u(null,e,t,n)},c.TYPED_ARRAY_SUPPORT&&(c.prototype.__proto__=Uint8Array.prototype,c.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&c[Symbol.species]===c&&Object.defineProperty(c,Symbol.species,{value:null,configurable:!0})),c.alloc=function(e,t,n){return function(e,t,n,r){return l(t),t<=0?s(e,t):void 0!==n?"string"==typeof r?s(e,t).fill(n,r):s(e,t).fill(n):s(e,t)}(null,e,t,n)},c.allocUnsafe=function(e){return f(null,e)},c.allocUnsafeSlow=function(e){return f(null,e)},c.isBuffer=function(e){return!(null==e||!e._isBuffer)},c.compare=function(e,t){if(!c.isBuffer(e)||!c.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0},c.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},c.concat=function(e,t){if(!i(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return c.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=c.allocUnsafe(t),o=0;for(n=0;n<e.length;++n){var a=e[n];if(!c.isBuffer(a))throw new TypeError('"list" argument must be an Array of Buffers');a.copy(r,o),o+=a.length}return r},c.byteLength=d,c.prototype._isBuffer=!0,c.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)g(this,t,t+1);return this},c.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)g(this,t,t+3),g(this,t+1,t+2);return this},c.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)g(this,t,t+7),g(this,t+1,t+6),g(this,t+2,t+5),g(this,t+3,t+4);return this},c.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?I(this,0,e):function(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return x(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return _(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},c.prototype.equals=function(e){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===c.compare(this,e)},c.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),"<Buffer "+e+">"},c.prototype.compare=function(e,t,n,r,o){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),u=this.slice(r,o),l=e.slice(t,n),f=0;f<s;++f)if(u[f]!==l[f]){i=u[f],a=l[f];break}return i<a?-1:a<i?1:0},c.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},c.prototype.indexOf=function(e,t,n){return y(this,e,t,n,!0)},c.prototype.lastIndexOf=function(e,t,n){return y(this,e,t,n,!1)},c.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(127&e[o]);return r}function P(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(e[o]);return r}function x(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=t;i<n;++i)o+=N(e[i]);return o}function R(e,t,n){for(var r=e.slice(t,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function D(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function O(e,t,n,r,o,i){if(!c.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||t<i)throw new RangeError('"value" argument is out of bounds');if(n+r>e.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o<i;++o)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function M(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o<i;++o)e[n+o]=t>>>8*(r?o:3-o)&255}function A(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||A(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function j(e,t,n,r,i){return i||A(e,0,n,8),o.write(e,t,n,r,52,8),n+8}c.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),c.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=c.prototype;else{var o=t-e;n=new c(o,void 0);for(var i=0;i<o;++i)n[i]=this[i+e]}return n},c.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r},c.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e+--t],o=1;t>0&&(o*=256);)r+=this[e+--t]*o;return r},c.prototype.readUInt8=function(e,t){return t||D(e,1,this.length),this[e]},c.prototype.readUInt16LE=function(e,t){return t||D(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUInt16BE=function(e,t){return t||D(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUInt32LE=function(e,t){return t||D(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUInt32BE=function(e,t){return t||D(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r>=(o*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},c.prototype.readInt8=function(e,t){return t||D(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},c.prototype.readInt16LE=function(e,t){t||D(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(e,t){t||D(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(e,t){return t||D(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return t||D(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!1,52,8)},c.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||O(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i<n&&(o*=256);)this[t+i]=e/o&255;return t+n},c.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||O(this,e,t,n,Math.pow(2,8*n)-1,0);var o=n-1,i=1;for(this[t+o]=255&e;--o>=0&&(i*=256);)this[t+o]=e/i&255;return t+n},c.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,255,0),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},c.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},c.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i<n&&(a*=256);)e<0&&0===s&&0!==this[t+i-1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},c.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},c.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,127,-128),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},c.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},c.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},c.prototype.writeDoubleLE=function(e,t,n){return j(this,e,t,!0,n)},c.prototype.writeDoubleBE=function(e,t,n){return j(this,e,t,!1,n)},c.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var o,i=r-n;if(this===e&&n<t&&t<r)for(o=i-1;o>=0;--o)e[o+t]=this[o+n];else if(i<1e3||!c.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)e[o+t]=this[o+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+i),t);return i},c.prototype.fill=function(e,t,n,r){if("string"==typeof e){if("string"==typeof t?(r=t,t=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===e.length){var o=e.charCodeAt(0);o<256&&(e=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!c.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError("Out of range index");if(n<=t)return this;var i;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i<n;++i)this[i]=e;else{var a=c.isBuffer(e)?e:F(new c(e,r).toString()),s=a.length;for(i=0;i<n-t;++i)this[i+t]=a[i%s]}return this};var U=/[^+\/0-9A-Za-z-_]/g;function N(e){return e<16?"0"+e.toString(16):e.toString(16)}function F(e,t){var n;t=t||1/0;for(var r=e.length,o=null,i=[],a=0;a<r;++a){if((n=e.charCodeAt(a))>55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o<r&&!(o+n>=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(9))},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}()},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.write=function(t){return""+t+e.RecordSeparator},e.parse=function(t){if(t[t.length-1]!==e.RecordSeparator)throw new Error("Message is incomplete.");var n=t.split(e.RecordSeparator);return n.pop(),n},e.RecordSeparatorCode=30,e.RecordSeparator=String.fromCharCode(e.RecordSeparatorCode),e}()},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r=n(23),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(21);i.inherits=n(15);var a=n(36),s=n(41);i.inherits(f,a);for(var c=o(s.prototype),u=0;u<c.length;u++){var l=c[u];f.prototype[l]||(f.prototype[l]=s.prototype[l])}function f(e){if(!(this instanceof f))return new f(e);a.call(this,e),s.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",h)}function h(){this.allowHalfOpen||this._writableState.ended||r.nextTick(p,this)}function p(e){e.end()}Object.defineProperty(f.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(f.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),f.prototype._destroy=function(e,t){this.push(null),this.end(),r.nextTick(t,e)}},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(53),i=n(22),a=n(65),s=n(68),c=n(69);e.exports=function(e){var t=[],n=[];return{encode:c(t,(e=e||{forceFloat64:!1,compatibilityMode:!1,disableTimestampEncoding:!1}).forceFloat64,e.compatibilityMode,e.disableTimestampEncoding),decode:s(n),register:function(e,t,n,a){return o(t,"must have a constructor"),o(n,"must have an encode function"),o(e>=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17);var i,a=n(5),s=!1,c=!1,u=null;function l(e,t){var n=p(e);if(!t&&d(n))f(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function f(e,t){a.resetScrollAfterNextBatch(),history.pushState(null,"",e),h(t)}function h(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return u?[4,u(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(i=i||document.createElement("a")).href=e,i.href}function d(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(u=e,c)return;c=!0,window.addEventListener("popstate",function(){return h(!1)})},enableNavigationInterception:function(){s=!0},navigateTo:l,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(s&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));d(r)&&(e.preventDefault(),f(r,!0))}}})},t.navigateTo=l},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),i=p("_blazorLogicalEnd");function a(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(u(i)&&u(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(c(i))throw new Error("Not implemented: moving existing logical children");var a=u(t);if(n<a.length){var s=a[n];s.parentNode.insertBefore(e,s),a.splice(n,0,i)}else h(e,t),a.push(i);i[o]=t,r in i||(i[r]=[])}function c(e){return e[o]||null}function u(e){return e[r]}function l(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function f(e){var t=u(c(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function h(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=f(t);n?n.parentNode.insertBefore(e,n):h(e,c(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=a(n,!0),s=u(r);return Array.from(n.childNodes).forEach(function(e){return s.push(e)}),e[o]=r,t&&(e[i]=t,a(t,!0)),a(e,!0)},t.toLogicalElement=a,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return s(n,e,t),n},t.insertLogicalChild=s,t.removeLogicalChild=function e(t,n){var r=u(t).splice(n,1)[0];if(r instanceof Comment)for(var o=u(r);o.length>0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=c,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return u(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=u,t.permuteLogicalChildren=function(e,t){var n=u(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=c(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t,n,r){var o=u();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),a=o.invokeDotNetFromJS(e,t,n,i);return a?f(a):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function c(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var a=o++,s=new Promise(function(e,t){n[a]={resolve:e,reject:t}});try{var c=JSON.stringify(i,g);u().beginInvokeDotNetFromJS(a,e,t,r,c)}catch(e){l(a,!1,e)}return s}function u(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=a,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return s(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return c(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,f(t));return null==n?null:JSON.stringify(n,g)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,f(n)))});e&&r.then(function(t){return u().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],g))},function(t){return u().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,h(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);l(parseInt(e),t,r)}};var d=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return s(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return c(null,e,this._id,t)},e.prototype.dispose=function(){c(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function g(e,t){return t instanceof d?t.serializeAsArg():t}a(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new d(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var c,u=[],l=!1,f=-1;function h(){l&&c&&(l=!1,c.length?u=c.concat(u):f=-1,u.length&&p())}function p(){if(!l){var e=s(h);l=!0;for(var t=u.length;t;){for(c=u,u=[];++f<t;)c&&c[f].run();f=-1,t=u.length}c=null,l=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===a||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function d(e,t){this.fun=e,this.array=t}function g(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];u.push(new d(e,t)),1!==u.length||l||s(p)},d.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=g,o.addListener=g,o.once=g,o.off=g,o.removeListener=g,o.removeAllListeners=g,o.emit=g,o.prependListener=g,o.prependOnceListener=g,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(e,t,n){(function(e){function n(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===n(e)},t.isBoolean=function(e){return"boolean"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return"[object RegExp]"===n(e)},t.isObject=function(e){return"object"==typeof e&&null!==e},t.isDate=function(e){return"[object Date]"===n(e)},t.isError=function(e){return"[object Error]"===n(e)||e instanceof Error},t.isFunction=function(e){return"function"==typeof e},t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,n(6).Buffer)},function(e,t,n){var r=n(56),o=n(34),i=n(14).Buffer;function a(e){if(!(this instanceof a))return new a(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else this.append(e);r.call(this)}o.inherits(a,r),a.prototype._offset=function(e){var t,n=0,r=0;if(0===e)return[0,0];for(;r<this._bufs.length;r++){if(e<(t=n+this._bufs[r].length)||r==this._bufs.length-1)return[r,e-n];n=t}},a.prototype.append=function(e){var t=0;if(i.isBuffer(e))this._appendBuffer(e);else if(Array.isArray(e))for(;t<e.length;t++)this.append(e[t]);else if(e instanceof a)for(;t<e._bufs.length;t++)this.append(e._bufs[t]);else null!=e&&("number"==typeof e&&(e=e.toString()),this._appendBuffer(i.from(e)));return this},a.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length},a.prototype._write=function(e,t,n){this._appendBuffer(e),"function"==typeof n&&n()},a.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)},a.prototype.end=function(e){r.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},a.prototype.get=function(e){return this.slice(e,e+1)[0]},a.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},a.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,c=this._offset(n),u=r-n,l=u,f=s&&t||0,h=c[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a<this._bufs.length;a++)this._bufs[a].copy(e,f),f+=this._bufs[a].length;return e}if(l<=this._bufs[c[0]].length-h)return s?this._bufs[c[0]].copy(e,t,h,h+l):this._bufs[c[0]].slice(h,h+l);for(s||(e=i.allocUnsafe(u)),a=c[0];a<this._bufs.length;a++){if(!(l>(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;e<this._bufs.length;e++)t.append(this._bufs[e]);return t},a.prototype.destroy=function(){this._bufs.length=0,this.length=0,this.push(null)},function(){var e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1};for(var t in e)!function(t){a.prototype[t]=function(n){return this.slice(n,n+e[t])[t](0)}}(t)}(),e.exports=a},function(e,t,n){"use strict";(function(t){!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function(e,n,r,o){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var i,a,s=arguments.length;switch(s){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick(function(){e.call(null,n)});case 3:return t.nextTick(function(){e.call(null,n,r)});case 4:return t.nextTick(function(){e.call(null,n,r,o)});default:for(i=new Array(s-1),a=0;a<i.length;)i[a++]=arguments[a];return t.nextTick(function(){e.apply(null,i)})}}}:e.exports=t}).call(this,n(20))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(12),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),i=n(13),a=n(31),s=n(19),c=n(12),u=document.createElement("template"),l=document.createElementNS("http://www.w3.org/2000/svg","g"),f={submit:!0},h={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){f[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};s.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)}),c.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),h[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var a=h[t];if(a){var s=i.getLogicalSiblingEnd(a);delete h[t],s?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,a=r.indexOf(t),s=o;s<=a;s++)i.removeLogicalChild(n,o);e.textContent="!"}(a,s):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(a)}var c=i.getClosestDomElement(o).ownerDocument,u=c&&c.activeElement;this.applyEdits(e,t,o,0,n,r),u instanceof HTMLElement&&c&&c.activeElement!==u&&u.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,a,s){for(var c,u=0,l=o,f=e.arrayBuilderSegmentReader,h=e.editReader,p=e.frameReader,d=f.values(a),g=f.offset(a),y=g+f.count(a),v=g;v<y;v++){var b=e.diffReader.editsEntry(d,v),m=h.editType(b);switch(m){case r.EditType.prependFrame:var w=h.newTreeIndex(b),E=e.referenceFramesEntry(s,w),S=h.siblingIndex(b);this.insertFrame(e,t,n,l+S,s,E,w);break;case r.EditType.removeFrame:S=h.siblingIndex(b);i.removeLogicalChild(n,l+S);break;case r.EditType.setAttribute:w=h.newTreeIndex(b),E=e.referenceFramesEntry(s,w),S=h.siblingIndex(b);if(!((C=i.getLogicalChild(n,l+S))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,C,E);break;case r.EditType.removeAttribute:var C;S=h.siblingIndex(b);if(!((C=i.getLogicalChild(n,l+S))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var _=h.removedAttributeName(b);this.tryApplySpecialProperty(e,C,_,null)||C.removeAttribute(_);break;case r.EditType.updateText:w=h.newTreeIndex(b),E=e.referenceFramesEntry(s,w),S=h.siblingIndex(b);var I=i.getLogicalChild(n,l+S);if(!(I instanceof Text))throw new Error("Cannot set text content on non-text child");I.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=h.newTreeIndex(b),E=e.referenceFramesEntry(s,w),S=h.siblingIndex(b);i.removeLogicalChild(n,l+S),this.insertMarkup(e,n,l+S,E);break;case r.EditType.stepIn:S=h.siblingIndex(b);n=i.getLogicalChild(n,l+S),u++,l=0;break;case r.EditType.stepOut:n=i.getLogicalParent(n),l=0===--u?o:0;break;case r.EditType.permutationListEntry:(c=c||[]).push({fromSiblingIndex:l+h.siblingIndex(b),toSiblingIndex:l+h.moveToSiblingIndex(b)});break;case r.EditType.permutationListEnd:i.permuteLogicalChildren(n,c),c=void 0;break;default:throw new Error("Unknown edit type: "+m)}}},e.prototype.insertFrame=function(e,t,n,o,i,s,c){var u=e.frameReader,l=u.frameType(s);switch(l){case r.FrameType.element:return this.insertElement(e,t,n,o,i,s,c),1;case r.FrameType.text:return this.insertText(e,n,o,s),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,s),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,i,c+1,c+u.subtreeLength(s));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return a.applyCaptureIdToElement(n,u.elementReferenceCaptureId(s)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,s),1;default:throw new Error("Unknown frame type: "+l)}},e.prototype.insertElement=function(e,t,n,o,a,s,c){var u=e.frameReader,l=u.elementName(s),f="svg"===l||i.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",l):document.createElement(l),h=i.toLogicalElement(f);i.insertLogicalChild(f,n,o);for(var p=c+u.subtreeLength(s),d=c+1;d<p;d++){var g=e.referenceFramesEntry(a,d);if(u.frameType(g)!==r.FrameType.attribute){this.insertFrameRange(e,t,h,0,a,d,p);break}this.applyAttribute(e,t,f,g)}if(f instanceof HTMLSelectElement&&"_blazorSelectValue"in f){var y=f._blazorSelectValue;f.value=y,delete f._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=i.createAndInsertLogicalContainer(t,n),a=e.frameReader.componentId(r);this.attachComponentToElement(a,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),a=document.createTextNode(o);i.insertLogicalChild(a,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,a=i.createAndInsertLogicalContainer(t,n),s=e.frameReader.markupContent(r),c=(o=s,i.isSvgElement(t)?(l.innerHTML=o||" ",l):(u.innerHTML=o||" ",u.content)),f=0;c.firstChild;)i.insertLogicalChild(c.firstChild,a,f++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,i=o.attributeName(r),a=o.attributeEventHandlerId(r);if(a){var s=g(i);this.eventDelegator.setListener(n,s,a,t)}else this.tryApplySpecialProperty(e,n,i,r)||n.setAttribute(i,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var i=g(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,i,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");i=g(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,i,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var i=n?r.attributeValue(n):null;return t.value=i,"SELECT"===t.tagName&&(t._blazorSelectValue=i),!0;case"OPTION":(i=n?r.attributeValue(n):null)?t.setAttribute("value",i):t.removeAttribute("value");var a=this.findClosestAncestorSelectElement(t);return a&&"_blazorSelectValue"in a&&a._blazorSelectValue===i&&(this.tryApplyValueProperty(e,a,n),delete a._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,i,a){for(var s=r,c=i;c<a;c++){var u=e.referenceFramesEntry(o,c);r+=this.insertFrame(e,t,n,r,o,u,c),c+=d(e,u)}return r-s},e}();function d(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function g(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),i=l(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),a=l(["click","dblclick","mousedown","mousemove","mouseup"]),s=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new c(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),i=o.getHandler(t);if(i)this.eventInfoStore.update(i.eventHandlerId,n);else{var a={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(a),o.setHandler(t,a)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,s=e.target,c=null,u=i.hasOwnProperty(e.type),l=!1;s;){var f=this.getEventHandlerInfosForElement(s,!1);if(f){var h=f.getHandler(e.type);if(h&&(t=s,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&a.hasOwnProperty(n)&&t.disabled))){c||(c=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(h.renderingComponentId,e);this.onEvent(e,h.eventHandlerId,c,p)}f.stopPropagation(e.type)&&(l=!0),f.preventDefault(e.type)&&e.preventDefault()}s=u||l?null:s.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new u:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=s;var c=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=i.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),u=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function l(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==a.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var s=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:s});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},i(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",i(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},i(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},i(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function i(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var a=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),i||(i=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},function(e,t,n){(function(e){var r=Object.getOwnPropertyDescriptors||function(e){for(var t=Object.keys(e),n={},r=0;r<t.length;r++)n[t[r]]=Object.getOwnPropertyDescriptor(e,t[r]);return n},o=/%[sdj%]/g;t.format=function(e){if(!v(e)){for(var t=[],n=0;n<arguments.length;n++)t.push(s(arguments[n]));return t.join(" ")}n=1;for(var r=arguments,i=r.length,a=String(e).replace(o,function(e){if("%%"===e)return"%";if(n>=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),c=r[n];n<i;c=r[++n])g(c)||!w(c)?a+=" "+c:a+=" "+s(c);return a},t.deprecate=function(n,r){if(void 0!==e&&!0===e.noDeprecation)return n;if(void 0===e)return function(){return t.deprecate(n,r).apply(this,arguments)};var o=!1;return function(){if(!o){if(e.throwDeprecation)throw new Error(r);e.traceDeprecation?console.trace(r):console.error(r),o=!0}return n.apply(this,arguments)}};var i,a={};function s(e,n){var r={seen:[],stylize:u};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=c),l(r,e,r.depth)}function c(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function u(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&C(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(C(n)){var c=n.name?": "+n.name:"";return e.stylize("[Function"+c+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var u,w="",_=!1,I=["{","}"];(p(n)&&(_=!0,I=["[","]"]),C(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||_&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),u=_?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a<s;++a)k(t,String(a))?i.push(h(e,t,n,r,String(a),!0)):i.push("");return o.forEach(function(o){o.match(/^\d+$/)||i.push(h(e,t,n,r,o,!0))}),i}(e,n,r,s,a):a.map(function(t){return h(e,n,r,s,t,_)}),e.seen.pop(),function(e,t,n){if(e.reduce(function(e,t){return 0,t.indexOf("\n")>=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(u,w,I)):I[0]+w+I[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,c;if((c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(s=e.stylize("[Setter]","special")),k(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(c.value)<0?(s=g(n)?l(e,c.value,null):l(e,c.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),b(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===_(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===_(e)}function S(e){return w(e)&&("[object Error]"===_(e)||e instanceof Error)}function C(e){return"function"==typeof e}function _(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=C,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(54);var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":"),[e.getDate(),T[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(55),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function x(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i<arguments.length;i++)o.push(arguments[i]);o.push(function(e,r){e?n(e):t(r)});try{e.apply(this,o)}catch(e){n(e)}return r}return Object.setPrototypeOf(t,Object.getPrototypeOf(e)),P&&Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),Object.defineProperties(t,r(e))},t.promisify.custom=P,t.callbackify=function(t){if("function"!=typeof t)throw new TypeError('The "original" argument must be of type Function');function n(){for(var n=[],r=0;r<arguments.length;r++)n.push(arguments[r]);var o=n.pop();if("function"!=typeof o)throw new TypeError("The last argument must be of type Function");var i=this,a=function(){return o.apply(i,arguments)};t.apply(this,n).then(function(t){e.nextTick(a,null,t)},function(t){e.nextTick(x,t,a)})}return Object.setPrototypeOf(n,Object.getPrototypeOf(t)),Object.defineProperties(n,r(t)),n}}).call(this,n(20))},,function(e,t,n){"use strict";(function(t,r){var o=n(23);e.exports=m;var i,a=n(57);m.ReadableState=b;n(37).EventEmitter;var s=function(e,t){return e.listeners(t).length},c=n(38),u=n(14).Buffer,l=t.Uint8Array||function(){};var f=n(21);f.inherits=n(15);var h=n(58),p=void 0;p=h&&h.debuglog?h.debuglog("stream"):function(){};var d,g=n(59),y=n(39);f.inherits(m,c);var v=["error","close","destroy","pause","resume"];function b(e,t){e=e||{};var r=t instanceof(i=i||n(10));this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var o=e.highWaterMark,a=e.readableHighWaterMark,s=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(a||0===a)?a:s,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new g,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(d||(d=n(40).StringDecoder),this.decoder=new d(e.encoding),this.encoding=e.encoding)}function m(e){if(i=i||n(10),!(this instanceof m))return new m(e);this._readableState=new b(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),c.call(this)}function w(e,t,n,r,o){var i,a=e._readableState;null===t?(a.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,_(e)}(e,a)):(o||(i=function(e,t){var n;r=t,u.isBuffer(r)||r instanceof l||"string"==typeof t||void 0===t||e.objectMode||(n=new TypeError("Invalid non-string/buffer chunk"));var r;return n}(a,t)),i?e.emit("error",i):a.objectMode||t&&t.length>0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):T(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(a)}function E(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(e.emit("data",n),e.read(0)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&_(e)),T(e,t)}Object.defineProperty(m.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),m.prototype.destroy=y.destroy,m.prototype._undestroy=y.undestroy,m.prototype._destroy=function(e,t){this.push(null),t(e)},m.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=u.from(e,t),t=""),n=!0),w(this,e,t,!1,n)},m.prototype.unshift=function(e){return w(this,e,null,!0,!1)},m.prototype.isPaused=function(){return!1===this._readableState.flowing},m.prototype.setEncoding=function(e){return d||(d=n(40).StringDecoder),this._readableState.decoder=new d(e),this._readableState.encoding=e,this};var S=8388608;function C(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function _(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(I,e):I(e))}function I(e){p("emit readable"),e.emit("readable"),R(e)}function T(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(p("maybeReadMore read 0"),e.read(0),n!==t.length);)n=t.length;t.readingMore=!1}function P(e){p("readable nexttick read 0"),e.read(0)}function x(e,t){t.reading||(p("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),R(e),t.flowing&&!t.reading&&e.read(0)}function R(e){var t=e._readableState;for(p("flow",t.flowing);t.flowing&&null!==e.read(););}function D(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;e<t.head.data.length?(r=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):r=e===t.head.data.length?t.shift():n?function(e,t){var n=t.head,r=1,o=n.data;e-=o.length;for(;n=n.next;){var i=n.data,a=e>i.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=u.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function O(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function M(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}m.prototype.read=function(e){p("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?O(this):_(this),null;if(0===(e=C(e,t))&&t.ended)return 0===t.length&&O(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e<t.highWaterMark)&&p("length less than watermark",o=!0),t.ended||t.reading?p("reading or ended",o=!1):o&&(p("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=C(n,t))),null===(r=e>0?D(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&O(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function u(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,R(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==M(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<o;i++)r[i].emit("unpipe",this,n);return this}var a=M(t.pipes,e);return-1===a?this:(t.pipes.splice(a,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n),this)},m.prototype.on=function(e,t){var n=c.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var r=this._readableState;r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.emittedReadable=!1,r.reading?r.length&&_(this):o.nextTick(P,this))}return n},m.prototype.addListener=m.prototype.on,m.prototype.resume=function(){var e=this._readableState;return e.flowing||(p("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,o.nextTick(x,e,t))}(this,e)),this},m.prototype.pause=function(){return p("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(p("pause"),this._readableState.flowing=!1,this.emit("pause")),this},m.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var o in e.on("end",function(){if(p("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)}),e.on("data",function(o){(p("wrapped data"),n.decoder&&(o=n.decoder.write(o)),n.objectMode&&null==o)||(n.objectMode||o&&o.length)&&(t.push(o)||(r=!0,e.pause()))}),e)void 0===this[o]&&"function"==typeof e[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));for(var i=0;i<v.length;i++)e.on(v[i],this.emit.bind(this,v[i]));return this._read=function(t){p("wrapped _read",t),r&&(r=!1,e.resume())},this},Object.defineProperty(m.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),m._fromList=D}).call(this,n(9),n(20))},function(e,t,n){"use strict";var r,o="object"==typeof Reflect?Reflect:null,i=o&&"function"==typeof o.apply?o.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=o&&"function"==typeof o.ownKeys?o.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var a=Number.isNaN||function(e){return e!=e};function s(){s.init.call(this)}e.exports=s,s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var c=10;function u(e){return void 0===e._maxListeners?s.defaultMaxListeners:e._maxListeners}function l(e,t,n,r){var o,i,a,s;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),a=i[t]),void 0===a)a=i[t]=n,++e._eventsCount;else if("function"==typeof a?a=i[t]=r?[n,a]:[a,n]:r?a.unshift(n):a.push(n),(o=u(e))>0&&a.length>o&&!a.warned){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,s=c,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t<arguments.length;t++)e.push(arguments[t]);this.fired||(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,i(this.listener,this.target,e))}.bind(r);return o.listener=n,r.wrapFn=o,o}function h(e,t,n){var r=e._events;if(void 0===r)return[];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(o):d(o,o.length)}function p(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}Object.defineProperty(s,"defaultMaxListeners",{enumerable:!0,get:function(){return c},set:function(e){if("number"!=typeof e||e<0||a(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");c=e}}),s.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},s.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||a(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},s.prototype.getMaxListeners=function(){return u(this)},s.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,o=this._events;if(void 0!==o)r=r&&void 0===o.error;else if(!r)return!1;if(r){var a;if(t.length>0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=o[e];if(void 0===c)return!1;if("function"==typeof c)i(c,this,t);else{var u=c.length,l=d(c,u);for(n=0;n<u;++n)i(l[n],this,t)}return!0},s.prototype.addListener=function(e,t){return l(this,e,t,!1)},s.prototype.on=s.prototype.addListener,s.prototype.prependListener=function(e,t){return l(this,e,t,!0)},s.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.on(e,f(this,e,t)),this},s.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.prependListener(e,f(this,e,t)),this},s.prototype.removeListener=function(e,t){var n,r,o,i,a;if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);if(void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(o=-1,i=n.length-1;i>=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(n,o),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,a||t)}return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var o,i=Object.keys(n);for(r=0;r<i.length;++r)"removeListener"!==(o=i[r])&&this.removeAllListeners(o);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(37).EventEmitter},function(e,t,n){"use strict";var r=n(23);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(61).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=u,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},i.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},i.prototype.text=function(e,t){var n=function(e,t,n){var r=t.length-1;if(r<n)return 0;var o=a(t[r]);if(o>=0)return o>0&&(e.lastNeed=o-1),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(e.lastNeed=o-2),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(23);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var s,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var u=n(21);u.inherits=n(15);var l={deprecate:n(64)},f=n(38),h=n(14).Buffer,p=o.Uint8Array||function(){};var d,g=n(39);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,u=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(_,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),_(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?c(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function b(e){if(s=s||n(10),!(d.call(b,this)||this instanceof s))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),_(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,c=!0;n;)o[s]=n,n.isBuf||(c=!1),n=n.next,s+=1;o.allBuffers=c,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var u=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:u.length,u,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),_(e,t)})}function _(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(C,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}u.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var c=t.length<t.highWaterMark;c||(t.needDrain=!0);if(t.writing||t.corked){var u=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:o,isBuf:n,callback:i,next:null},u?u.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else m(e,t,!1,s,r,o,i);return c}(this,o,s,e,t,n)),a},b.prototype.cork=function(){this._writableState.corked++},b.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||E(this,e))},b.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,_(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(20),n(62).setImmediate,n(9))},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(21);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}function a(e){if(!(this instanceof a))return new a(e);r.call(this,e),this._transformState={afterTransform:i.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",s)}function s(){var e=this;"function"==typeof this._flush?this._flush(function(t,n){c(e,t,n)}):c(this,null,null)}function c(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new Error("Calling transform done when ws.length != 0");if(e._transformState.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}o.inherits=n(15),o.inherits(a,r),a.prototype.push=function(e,t){return this._transformState.needTransform=!1,r.prototype.push.call(this,e,t)},a.prototype._transform=function(e,t,n){throw new Error("_transform() is not implemented")},a.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var o=this._readableState;(r.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},a.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},a.prototype._destroy=function(e,t){var n=this;r.prototype._destroy.call(this,e,function(e){t(e),n.emit("close")})}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return h});var r,o,i=n(3),a=n(4),s=n(0),c=n(1),u=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e};if("undefined"==typeof XMLHttpRequest){var f=require;o=f("request")}var h=function(t){function n(e){var n=t.call(this)||this;if(void 0===o)throw new Error("The 'request' module could not be loaded.");return n.logger=e,n.cookieJar=o.jar(),n.request=o.defaults({jar:n.cookieJar}),n}return u(n,t),n.prototype.send=function(t){var n=this;return new Promise(function(r,o){var u;u=Object(c.g)(t.content)?e.from(t.content):t.content||"";var f=n.request(t.url,{body:u,encoding:"arraybuffer"===t.responseType?null:"utf8",headers:l({"X-Requested-With":"XMLHttpRequest"},t.headers),method:t.method,timeout:t.timeout},function(e,c,u){if(t.abortSignal&&(t.abortSignal.onabort=null),e)return"ETIMEDOUT"===e.code&&(n.logger.log(s.a.Warning,"Timeout from HTTP request."),o(new i.c)),n.logger.log(s.a.Warning,"Error from HTTP request. "+e),void o(e);c.statusCode>=200&&c.statusCode<300?r(new a.b(c.statusCode,c.statusMessage||"",u)):o(new i.b(c.statusMessage||"",c.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(a.a)}).call(this,n(6).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(8),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var a=new Uint8Array(t);if(-1===(c=a.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var s=c+1;n=String.fromCharCode.apply(null,a.slice(0,s)),i=a.byteLength>s?a.slice(s).buffer:null}else{var c,u=t;if(-1===(c=u.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=c+1;n=u.substring(0,s),i=u.length>s?u.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(6).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}},i=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a},a=this&&this.__spread||function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(i(arguments[t]));return e};Object.defineProperty(t,"__esModule",{value:!0}),n(17),n(24);var s=n(2),c=n(79),u=n(32),l=n(33),f=n(70),h=n(73),p=n(16),d=n(74),g=n(19),y=n(75),v=n(76),b=n(5),m=!1,w=!1;function E(e){return r(this,void 0,void 0,function(){var t,n,i,a,s,c,u=this;return o(this,function(l){switch(l.label){case 0:if(w)throw new Error("Blazor has already started.");return w=!0,t=y.resolveOptions(e),n=new h.ConsoleLogger(t.logLevel),window.Blazor.defaultReconnectionHandler=new v.DefaultReconnectionHandler(n),t.reconnectionHandler=t.reconnectionHandler||window.Blazor.defaultReconnectionHandler,n.log(p.LogLevel.Information,"Starting up blazor server-side application."),i=d.discoverComponents(document),a=new d.CircuitDescriptor(i),[4,S(t,n,a)];case 1:return s=l.sent(),[4,a.startCircuit(s)];case 2:return l.sent()?(c=function(e){return r(u,void 0,void 0,function(){var r,i;return o(this,function(o){switch(o.label){case 0:return m?[2,!1]:(i=e)?[3,2]:[4,S(t,n,a)];case 1:i=o.sent(),o.label=2;case 2:return r=i,[4,a.reconnect(r)];case 3:return o.sent()?(t.reconnectionHandler.onConnectionUp(),[2,!0]):(n.log(p.LogLevel.Information,"Reconnection attempt to the circuit was rejected by the server. This may indicate that the associated state is no longer available on the server."),[2,!1])}})})},window.addEventListener("unload",function(){var e=new FormData,t=a.circuitId;e.append("circuitId",t),navigator.sendBeacon("_blazor/disconnect",e)},!1),window.Blazor.reconnect=c,n.log(p.LogLevel.Information,"Blazor server-side application started."),[2]):(n.log(p.LogLevel.Error,"Failed to start the circuit."),[2])}})})}function S(e,t,n){return r(this,void 0,void 0,function(){var r,i,l,h,d;return o(this,function(o){switch(o.label){case 0:(r=new c.MessagePackHubProtocol).name="blazorpack",i=(new s.HubConnectionBuilder).withUrl("_blazor").withHubProtocol(r),e.configureSignalR(i),l=i.build(),g.setEventDispatcher(function(e,t){return l.send("DispatchBrowserEvent",JSON.stringify(e),JSON.stringify(t))}),window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return l.send("OnLocationChanged",e,t)}),l.on("JS.AttachComponent",function(e,t){return b.attachRootComponentToLogicalElement(0,n.resolveElement(t),e)}),l.on("JS.BeginInvokeJS",DotNet.jsCallDispatcher.beginInvokeJSFromDotNet),l.on("JS.EndInvokeDotNet",function(e){var t;return(t=DotNet.jsCallDispatcher).endInvokeDotNetFromJS.apply(t,a(JSON.parse(e)))}),h=f.RenderQueue.getOrCreate(t),l.on("JS.RenderBatch",function(e,n){t.log(p.LogLevel.Debug,"Received render batch with id "+e+" and "+n.byteLength+" bytes."),h.processBatch(e,n,l)}),l.onclose(function(t){return!m&&e.reconnectionHandler.onConnectionDown(e.reconnectionOptions,t)}),l.on("JS.Error",function(e){m=!0,C(l,e,t),u.showErrorNotification()}),window.Blazor._internal.forceCloseConnection=function(){return l.stop()},o.label=1;case 1:return o.trys.push([1,3,,4]),[4,l.start()];case 2:return o.sent(),[3,4];case 3:return d=o.sent(),C(l,d,t),[3,4];case 4:return DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,t,n,r,o){l.send("BeginInvokeDotNetFromJS",e?e.toString():null,t,n,r||0,o)},endInvokeJSFromDotNet:function(e,t,n){l.send("EndInvokeJSFromDotNet",e,t,n)}}),[2,l]}})})}function C(e,t,n){n.log(p.LogLevel.Error,t),e&&e.stop()}window.Blazor.start=E,l.shouldAutoStart()&&E()},function(e,t,n){"use strict";t.byteLength=function(e){var t=u(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=u(e),r=n[0],a=n[1],s=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,a)),c=0,l=a>0?r-4:r,f=0;f<l;f+=4)t=o[e.charCodeAt(f)]<<18|o[e.charCodeAt(f+1)]<<12|o[e.charCodeAt(f+2)]<<6|o[e.charCodeAt(f+3)],s[c++]=t>>16&255,s[c++]=t>>8&255,s[c++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[c++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[c++]=t>>8&255,s[c++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;a<s;a+=16383)i.push(l(e,a,a+16383>s?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,c=a.length;s<c;++s)r[s]=a[s],o[a.charCodeAt(s)]=s;function u(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s<n;s+=3)o=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(255&e[s+2]),a.push(r[(i=o)>>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,c=(1<<s)-1,u=c>>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-u;else{if(i===c)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=u}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,c,u=8*i-o-1,l=(1<<u)-1,f=l>>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-a))<1&&(a--,c*=2),(t+=a+f>=1?h/c:h*Math.pow(2,1-f))*c>=2&&(a++,c/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*c-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<<o|s,u+=o;u>0;e[n+p]=255&a,p+=d,a/=256,u-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ +var r=n(55),o=n(56),i=n(57);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()<t)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=u.prototype:(null===e&&(e=new u(t)),e.length=t),e}function u(e,t,n){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return f(this,e)}return c(this,e,t,n)}function c(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);u.TYPED_ARRAY_SUPPORT?(e=t).__proto__=u.prototype:e=h(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!u.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|d(t,n),o=(e=a(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(u.isBuffer(t)){var n=0|p(t.length);return 0===(e=a(e,n)).length?e:(t.copy(e,0,0,n),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?a(e,0):h(e,t);if("Buffer"===t.type&&i(t.data))return h(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function l(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function f(e,t){if(l(t),e=a(e,t<0?0:0|p(t)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function h(e,t){var n=t.length<0?0:0|p(t.length);e=a(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function p(e){if(e>=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,s=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(o){var l=-1;for(i=n;i<a;i++)if(c(e,i)===c(t,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===u)return l*s}else-1!==l&&(i-=i-l),l=-1}else for(n+u>a&&(n=a-u),i=n;i>=0;i--){for(var f=!0,h=0;h<u;h++)if(c(e,i+h)!==c(t,h)){f=!1;break}if(f)return i}return-1}function b(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;s<r;++s){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))return s;e[n+s]=a}return s}function m(e,t,n,r){return q(F(t,e.length-n),e,n,r)}function w(e,t,n,r){return q(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function E(e,t,n,r){return w(e,t,n,r)}function S(e,t,n,r){return q(H(t),e,n,r)}function _(e,t,n,r){return q(function(e,t){for(var n,r,o,i=[],s=0;s<e.length&&!((t-=2)<0);++s)n=e.charCodeAt(s),r=n>>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function C(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o<n;){var i,s,a,u,c=e[o],l=null,f=c>239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],s=e[o+2],128==(192&i)&&128==(192&s)&&(u=(15&c)<<12|(63&i)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],s=e[o+2],a=e[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=I)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=I));return n}(r)}t.Buffer=u,t.SlowBuffer=function(e){+e!=e&&(e=0);return u.alloc(+e)},t.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=s(),u.poolSize=8192,u._augment=function(e){return e.__proto__=u.prototype,e},u.from=function(e,t,n){return c(null,e,t,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(e,t,n){return function(e,t,n,r){return l(t),t<=0?a(e,t):void 0!==n?"string"==typeof r?a(e,t).fill(n,r):a(e,t).fill(n):a(e,t)}(null,e,t,n)},u.allocUnsafe=function(e){return f(null,e)},u.allocUnsafeSlow=function(e){return f(null,e)},u.isBuffer=function(e){return!(null==e||!e._isBuffer)},u.compare=function(e,t){if(!u.isBuffer(e)||!u.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0},u.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(e,t){if(!i(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return u.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=u.allocUnsafe(t),o=0;for(n=0;n<e.length;++n){var s=e[n];if(!u.isBuffer(s))throw new TypeError('"list" argument must be an Array of Buffers');s.copy(r,o),o+=s.length}return r},u.byteLength=d,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)g(this,t,t+1);return this},u.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)g(this,t,t+3),g(this,t+1,t+2);return this},u.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)g(this,t,t+7),g(this,t+1,t+6),g(this,t+2,t+5),g(this,t+3,t+4);return this},u.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?C(this,0,e):function(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),"<Buffer "+e+">"},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),s=(n>>>=0)-(t>>>=0),a=Math.min(i,s),c=this.slice(r,o),l=e.slice(t,n),f=0;f<a;++f)if(c[f]!==l[f]){i=c[f],s=l[f];break}return i<s?-1:s<i?1:0},u.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},u.prototype.indexOf=function(e,t,n){return y(this,e,t,n,!0)},u.prototype.lastIndexOf=function(e,t,n){return y(this,e,t,n,!1)},u.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var I=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(127&e[o]);return r}function P(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(e[o]);return r}function R(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=t;i<n;++i)o+=N(e[i]);return o}function x(e,t,n){for(var r=e.slice(t,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function A(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function D(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||t<i)throw new RangeError('"value" argument is out of bounds');if(n+r>e.length)throw new RangeError("Index out of range")}function O(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o<i;++o)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o<i;++o)e[n+o]=t>>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),u.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=u.prototype;else{var o=t-e;n=new u(o,void 0);for(var i=0;i<o;++i)n[i]=this[i+e]}return n},u.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r},u.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e+--t],o=1;t>0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||A(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||A(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||A(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||A(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||A(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r>=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||A(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||A(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||A(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||A(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||A(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i<n&&(o*=256);)this[t+i]=e/o&255;return t+n},u.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=n-1,i=1;for(this[t+o]=255&e;--o>=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=0,s=1,a=0;for(this[t]=255&e;++i<n&&(s*=256);)e<0&&0===a&&0!==this[t+i-1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=n-1,s=1,a=0;for(this[t+i]=255&e;--i>=0&&(s*=256);)e<0&&0===a&&0!==this[t+i+1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var o,i=r-n;if(this===e&&n<t&&t<r)for(o=i-1;o>=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)e[o+t]=this[o+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+i),t);return i},u.prototype.fill=function(e,t,n,r){if("string"==typeof e){if("string"==typeof t?(r=t,t=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===e.length){var o=e.charCodeAt(0);o<256&&(e=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!u.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError("Out of range index");if(n<=t)return this;var i;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i<n;++i)this[i]=e;else{var s=u.isBuffer(e)?e:F(new u(e,r).toString()),a=s.length;for(i=0;i<n-t;++i)this[i+t]=s[i%a]}return this};var j=/[^+\/0-9A-Za-z-_]/g;function N(e){return e<16?"0"+e.toString(16):e.toString(16)}function F(e,t){var n;t=t||1/0;for(var r=e.length,o=null,i=[],s=0;s<r;++s){if((n=e.charCodeAt(s))>55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(j,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o<r&&!(o+n>=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(37))},function(e,t,n){var r=n(62),o=n(36),i=n(13).Buffer;function s(e){if(!(this instanceof s))return new s(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else this.append(e);r.call(this)}o.inherits(s,r),s.prototype._offset=function(e){var t,n=0,r=0;if(0===e)return[0,0];for(;r<this._bufs.length;r++){if(e<(t=n+this._bufs[r].length)||r==this._bufs.length-1)return[r,e-n];n=t}},s.prototype.append=function(e){var t=0;if(i.isBuffer(e))this._appendBuffer(e);else if(Array.isArray(e))for(;t<e.length;t++)this.append(e[t]);else if(e instanceof s)for(;t<e._bufs.length;t++)this.append(e._bufs[t]);else null!=e&&("number"==typeof e&&(e=e.toString()),this._appendBuffer(i.from(e)));return this},s.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length},s.prototype._write=function(e,t,n){this._appendBuffer(e),"function"==typeof n&&n()},s.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)},s.prototype.end=function(e){r.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},s.prototype.get=function(e){return this.slice(e,e+1)[0]},s.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},s.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,s,a=!!e,u=this._offset(n),c=r-n,l=c,f=a&&t||0,h=u[1];if(0===n&&r==this.length){if(!a)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(s=0;s<this._bufs.length;s++)this._bufs[s].copy(e,f),f+=this._bufs[s].length;return e}if(l<=this._bufs[u[0]].length-h)return a?this._bufs[u[0]].copy(e,t,h,h+l):this._bufs[u[0]].slice(h,h+l);for(a||(e=i.allocUnsafe(c)),s=u[0];s<this._bufs.length;s++){if(!(l>(o=this._bufs[s].length-h))){this._bufs[s].copy(e,f,h,h+l);break}this._bufs[s].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},s.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new s(o)},s.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},s.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},s.prototype.duplicate=function(){for(var e=0,t=new s;e<this._bufs.length;e++)t.append(this._bufs[e]);return t},s.prototype.destroy=function(){this._bufs.length=0,this.length=0,this.push(null)},function(){var e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1};for(var t in e)!function(t){s.prototype[t]=function(n){return this.slice(n,n+e[t])[t](0)}}(t)}(),e.exports=s},function(e,t,n){"use strict";(function(t){!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function(e,n,r,o){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var i,s,a=arguments.length;switch(a){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick(function(){e.call(null,n)});case 3:return t.nextTick(function(){e.call(null,n,r)});case 4:return t.nextTick(function(){e.call(null,n,r,o)});default:for(i=new Array(a-1),s=0;s<i.length;)i[s++]=arguments[s];return t.nextTick(function(){e.apply(null,i)})}}}:e.exports=t}).call(this,n(23))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:s}catch(e){r=s}}();var u,c=[],l=!1,f=-1;function h(){l&&u&&(l=!1,u.length?c=u.concat(c):f=-1,c.length&&p())}function p(){if(!l){var e=a(h);l=!0;for(var t=c.length;t;){for(u=c,c=[];++f<t;)u&&u[f].run();f=-1,t=c.length}u=null,l=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===s||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function d(e,t){this.fun=e,this.array=t}function g(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new d(e,t)),1!==c.length||l||a(p)},d.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=g,o.addListener=g,o.once=g,o.off=g,o.removeListener=g,o.removeAllListeners=g,o.emit=g,o.prependListener=g,o.prependOnceListener=g,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(10),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),i=n(11),s=n(31),a=n(18),u=n(10),c=document.createElement("template"),l=document.createElementNS("http://www.w3.org/2000/svg","g"),f={submit:!0},h={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){f[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};a.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)}),u.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),h[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var s=h[t];if(s){var a=i.getLogicalSiblingEnd(s);delete h[t],a?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,s=r.indexOf(t),a=o;a<=s;a++)i.removeLogicalChild(n,o);e.textContent="!"}(s,a):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(s)}var u=i.getClosestDomElement(o).ownerDocument,c=u&&u.activeElement;this.applyEdits(e,t,o,0,n,r),c instanceof HTMLElement&&u&&u.activeElement!==c&&c.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,s,a){for(var u,c=0,l=o,f=e.arrayBuilderSegmentReader,h=e.editReader,p=e.frameReader,d=f.values(s),g=f.offset(s),y=g+f.count(s),v=g;v<y;v++){var b=e.diffReader.editsEntry(d,v),m=h.editType(b);switch(m){case r.EditType.prependFrame:var w=h.newTreeIndex(b),E=e.referenceFramesEntry(a,w),S=h.siblingIndex(b);this.insertFrame(e,t,n,l+S,a,E,w);break;case r.EditType.removeFrame:S=h.siblingIndex(b);i.removeLogicalChild(n,l+S);break;case r.EditType.setAttribute:w=h.newTreeIndex(b),E=e.referenceFramesEntry(a,w),S=h.siblingIndex(b);if(!((_=i.getLogicalChild(n,l+S))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,_,E);break;case r.EditType.removeAttribute:var _;S=h.siblingIndex(b);if(!((_=i.getLogicalChild(n,l+S))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var T=h.removedAttributeName(b);this.tryApplySpecialProperty(e,_,T,null)||_.removeAttribute(T);break;case r.EditType.updateText:w=h.newTreeIndex(b),E=e.referenceFramesEntry(a,w),S=h.siblingIndex(b);var C=i.getLogicalChild(n,l+S);if(!(C instanceof Text))throw new Error("Cannot set text content on non-text child");C.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=h.newTreeIndex(b),E=e.referenceFramesEntry(a,w),S=h.siblingIndex(b);i.removeLogicalChild(n,l+S),this.insertMarkup(e,n,l+S,E);break;case r.EditType.stepIn:S=h.siblingIndex(b);n=i.getLogicalChild(n,l+S),c++,l=0;break;case r.EditType.stepOut:n=i.getLogicalParent(n),l=0===--c?o:0;break;case r.EditType.permutationListEntry:(u=u||[]).push({fromSiblingIndex:l+h.siblingIndex(b),toSiblingIndex:l+h.moveToSiblingIndex(b)});break;case r.EditType.permutationListEnd:i.permuteLogicalChildren(n,u),u=void 0;break;default:throw new Error("Unknown edit type: "+m)}}},e.prototype.insertFrame=function(e,t,n,o,i,a,u){var c=e.frameReader,l=c.frameType(a);switch(l){case r.FrameType.element:return this.insertElement(e,t,n,o,i,a,u),1;case r.FrameType.text:return this.insertText(e,n,o,a),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,a),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,i,u+1,u+c.subtreeLength(a));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return s.applyCaptureIdToElement(n,c.elementReferenceCaptureId(a)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,a),1;default:throw new Error("Unknown frame type: "+l)}},e.prototype.insertElement=function(e,t,n,o,s,a,u){var c=e.frameReader,l=c.elementName(a),f="svg"===l||i.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",l):document.createElement(l),h=i.toLogicalElement(f);i.insertLogicalChild(f,n,o);for(var p=u+c.subtreeLength(a),d=u+1;d<p;d++){var g=e.referenceFramesEntry(s,d);if(c.frameType(g)!==r.FrameType.attribute){this.insertFrameRange(e,t,h,0,s,d,p);break}this.applyAttribute(e,t,f,g)}if(f instanceof HTMLSelectElement&&"_blazorSelectValue"in f){var y=f._blazorSelectValue;f.value=y,delete f._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=i.createAndInsertLogicalContainer(t,n),s=e.frameReader.componentId(r);this.attachComponentToElement(s,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),s=document.createTextNode(o);i.insertLogicalChild(s,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,s=i.createAndInsertLogicalContainer(t,n),a=e.frameReader.markupContent(r),u=(o=a,i.isSvgElement(t)?(l.innerHTML=o||" ",l):(c.innerHTML=o||" ",c.content)),f=0;u.firstChild;)i.insertLogicalChild(u.firstChild,s,f++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,i=o.attributeName(r),s=o.attributeEventHandlerId(r);if(s){var a=g(i);this.eventDelegator.setListener(n,a,s,t)}else this.tryApplySpecialProperty(e,n,i,r)||n.setAttribute(i,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var i=g(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,i,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");i=g(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,i,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var i=n?r.attributeValue(n):null;return t.value=i,"SELECT"===t.tagName&&(t._blazorSelectValue=i),!0;case"OPTION":(i=n?r.attributeValue(n):null)?t.setAttribute("value",i):t.removeAttribute("value");var s=this.findClosestAncestorSelectElement(t);return s&&"_blazorSelectValue"in s&&s._blazorSelectValue===i&&(this.tryApplyValueProperty(e,s,n),delete s._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,i,s){for(var a=r,u=i;u<s;u++){var c=e.referenceFramesEntry(o,u);r+=this.insertFrame(e,t,n,r,o,c,u),u+=d(e,c)}return r-a},e}();function d(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function g(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),i=l(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),s=l(["click","dblclick","mousedown","mousemove","mouseup"]),a=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new u(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),i=o.getHandler(t);if(i)this.eventInfoStore.update(i.eventHandlerId,n);else{var s={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(s),o.setHandler(t,s)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,a=e.target,u=null,c=i.hasOwnProperty(e.type),l=!1;a;){var f=this.getEventHandlerInfosForElement(a,!1);if(f){var h=f.getHandler(e.type);if(h&&(t=a,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&s.hasOwnProperty(n)&&t.disabled))){u||(u=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(h.renderingComponentId,e);this.onEvent(e,h.eventHandlerId,u,p)}f.stopPropagation(e.type)&&(l=!0),f.preventDefault(e.type)&&e.preventDefault()}a=c||l?null:a.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new c:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=a;var u=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=i.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),c=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function l(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==s.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var a=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:a});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},i(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",i(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},i(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},i(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function i(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var s=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),i||(i=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},function(e,t,n){"use strict";(function(e){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ -function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0}function o(e){return t.Buffer&&"function"==typeof t.Buffer.isBuffer?t.Buffer.isBuffer(e):!(null==e||!e._isBuffer)}var i=n(34),a=Object.prototype.hasOwnProperty,s=Array.prototype.slice,c="foo"===function(){}.name;function u(e){return Object.prototype.toString.call(e)}function l(e){return!o(e)&&("function"==typeof t.ArrayBuffer&&("function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(e):!!e&&(e instanceof DataView||!!(e.buffer&&e.buffer instanceof ArrayBuffer))))}var f=e.exports=v,h=/\s*function\s+([^\(\s]*)\s*/;function p(e){if(i.isFunction(e)){if(c)return e.name;var t=e.toString().match(h);return t&&t[1]}}function d(e,t){return"string"==typeof e?e.length<t?e:e.slice(0,t):e}function g(e){if(c||!i.isFunction(e))return i.inspect(e);var t=p(e);return"[Function"+(t?": "+t:"")+"]"}function y(e,t,n,r,o){throw new f.AssertionError({message:n,actual:e,expected:t,operator:r,stackStartFunction:o})}function v(e,t){e||y(e,!0,t,"==",f.ok)}function b(e,t,n,a){if(e===t)return!0;if(o(e)&&o(t))return 0===r(e,t);if(i.isDate(e)&&i.isDate(t))return e.getTime()===t.getTime();if(i.isRegExp(e)&&i.isRegExp(t))return e.source===t.source&&e.global===t.global&&e.multiline===t.multiline&&e.lastIndex===t.lastIndex&&e.ignoreCase===t.ignoreCase;if(null!==e&&"object"==typeof e||null!==t&&"object"==typeof t){if(l(e)&&l(t)&&u(e)===u(t)&&!(e instanceof Float32Array||e instanceof Float64Array))return 0===r(new Uint8Array(e.buffer),new Uint8Array(t.buffer));if(o(e)!==o(t))return!1;var c=(a=a||{actual:[],expected:[]}).actual.indexOf(e);return-1!==c&&c===a.expected.indexOf(t)||(a.actual.push(e),a.expected.push(t),function(e,t,n,r){if(null==e||null==t)return!1;if(i.isPrimitive(e)||i.isPrimitive(t))return e===t;if(n&&Object.getPrototypeOf(e)!==Object.getPrototypeOf(t))return!1;var o=m(e),a=m(t);if(o&&!a||!o&&a)return!1;if(o)return e=s.call(e),t=s.call(t),b(e,t,n);var c,u,l=S(e),f=S(t);if(l.length!==f.length)return!1;for(l.sort(),f.sort(),u=l.length-1;u>=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return u[c]=o,r(c),c++},h.clearImmediate=p}function p(e){delete u[e]}function d(e){if(l)setTimeout(d,0,e);else{var t=u[e];if(t){l=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{p(e),l=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(9),n(20))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(9))},function(e,t,n){"use strict";var r=n(66).Transform,o=n(15),i=n(22);function a(e){(e=e||{}).objectMode=!0,e.highWaterMark=16,r.call(this,e),this._msgpack=e.msgpack}function s(e){if(!(this instanceof s))return(e=e||{}).msgpack=this,new s(e);a.call(this,e)}function c(e){if(!(this instanceof c))return(e=e||{}).msgpack=this,new c(e);a.call(this,e),this._chunks=i()}o(a,r),o(s,a),s.prototype._transform=function(e,t,n){var r=null;try{r=this._msgpack.encode(e).slice(0)}catch(e){return this.emit("error",e),n()}this.push(r),n()},o(c,a),c.prototype._transform=function(e,t,n){e&&this._chunks.append(e);try{var r=this._msgpack.decode(this._chunks);this.push(r)}catch(e){return void(e instanceof this._msgpack.IncompleteBufferError?n():this.emit("error",e))}this._chunks.length>0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(34).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t<n)}(h,o))return null;switch(h){case 192:return n(null,1);case 194:return n(!1,1);case 195:return n(!0,1);case 204:return n(p=e.readUInt8(r+1),2);case 205:return n(p=e.readUInt16BE(r+1),3);case 206:return n(p=e.readUInt32BE(r+1),5);case 207:for(f=7;f>=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;s.push(u.value),t+=u.bytesConsumed,c+=u.bytesConsumed}return n(s,o+c)}function s(e,t,r,o){var a,s={},c=0;for(t+=o,a=0;a<r;a++){var u=i(e,t);if(!u)return null;var l=i(e,t+=u.bytesConsumed);if(!l)return null;s[u.value]=l.value,t+=l.bytesConsumed,c+=u.bytesConsumed+l.bytesConsumed}return n(s,o+c)}function c(e,t,n){var r=e.readInt8(t+1);return u(e,t,r,n,2)}function u(t,r,o,i,a){var s,c;if(r+=a,o<0)switch(o){case-1:return function(e,t,r){var o,i;switch(i=0,t){case 4:o=e.readUInt32BE(0);break;case 8:var a=e.readUInt32BE(0),s=e.readUInt32BE(4);i=a/4,o=(3&a)*Math.pow(2,32)+s;break;case 12:throw new Error("timestamp 96 is not yet implemented")}var c=1e3*o+Math.round(i/1e6);return n(new Date(c),t+r)}(c=t.slice(r,r+i),i,a)}for(s=0;s<e.length;s++){if(o===e[s].type)return c=t.slice(r,r+i),n(e[s].decode(c),a+i)}throw new Error("unable to find ext type "+o)}},e.exports.IncompleteBufferError=o},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(22),i=.1;function a(e,t){var n;return(n=r.allocUnsafe(5))[0]=202,n.writeFloatBE(e,1),(t||Math.abs(e-n.readFloatBE(1))>i)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n<e.length;n++)if(e[n].check(t)){i=e[n].encode(t);break}if(!i)return null;1==(a=i.length-1)?s.push(212):2===a?s.push(213):4===a?s.push(214):8===a?s.push(215):16===a?s.push(216):a<256?(s.push(199),s.push(a)):a<65536?(s.push(200),s.push(a>>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(5),a=n(71),s=n(16),c=function(){function e(e,t){this.nextBatchId=2,this.browserRendererId=e,this.logger=t}return e.getOrCreate=function(t){return e.instance||(e.instance=new e(0,t)),this.instance},e.prototype.processBatch=function(e,t,n){return r(this,void 0,void 0,function(){var r;return o(this,function(o){switch(o.label){case 0:return e<this.nextBatchId?[4,this.completeBatch(n,e)]:[3,2];case 1:return o.sent(),this.logger.log(s.LogLevel.Debug,"Batch "+e+" already processed. Waiting for batch "+this.nextBatchId+"."),[2];case 2:return e>this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<<r,i<128)break;r+=7}return n}(this.batchDataUint8,n),i=n+((t=o)<128?1:t<16384?2:t<2097152?3:4),a=new Uint8Array(this.batchDataUint8.buffer,this.batchDataUint8.byteOffset+i,o);return r.decodeUtf8(a)},e}(),f=function(){function e(e){this.batchDataUint8=e}return e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}(),h=function(){function e(e){this.batchDataUint8=e}return e.prototype.offset=function(e){return 0},e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}();function p(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function d(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t<n;){var i=e[t++];if(0===i)break;if(0==(128&i))r.push(i);else if(192==(224&i)){var a=63&e[t++];r.push((31&i)<<6|a)}else if(224==(240&i)){var a=63&e[t++],s=63&e[t++];r.push((31&i)<<12|a<<6|s)}else if(240==(248&i)){var a=63&e[t++],s=63&e[t++],c=63&e[t++],u=(7&i)<<18|a<<12|s<<6|c;u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(12),a=n(13),s=function(){function e(e){this.circuitId=void 0,this.components=e}return e.prototype.reconnect=function(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.invoke("ConnectCircuit",this.circuitId)},e.prototype.initialize=function(e){if(this.circuitId)throw new Error("Circuit host '"+this.circuitId+"' already initialized.");this.circuitId=e},e.prototype.startCircuit=function(e){return r(this,void 0,void 0,function(){var t;return o(this,function(n){switch(n.label){case 0:return[4,e.invoke("StartCircuit",i.internalFunctions.getBaseURI(),i.internalFunctions.getLocationHref(),JSON.stringify(this.components.map(function(e){return e.toRecord()})))];case 1:return(t=n.sent())?(this.initialize(t),[2,!0]):[2,!1]}})})},e.prototype.resolveElement=function(e){var t=Number.parseInt(e);if(Number.isNaN(t))throw new Error("Invalid sequence number '"+e+"'.");return a.toLogicalRootCommentElement(this.components[t].start,this.components[t].end)},e}();t.CircuitDescriptor=s;var c=function(){function e(e,t,n,r,o){this.type=e,this.start=t,this.end=n,this.sequence=r,this.descriptor=o}return e.prototype.toRecord=function(){return{type:this.type,sequence:this.sequence,descriptor:this.descriptor}},e}();t.ComponentDescriptor=c,t.discoverComponents=function(e){for(var t=function e(t){if(!t.hasChildNodes())return[];for(var n=[],r=new h(t.childNodes);r.next()&&r.currentElement;){var o=l(r);if(o)n.push(o);else for(var i=e(r.currentElement),a=0;a<i.length;a++){var s=i[a];n.push(s)}}return n}(e),n=[],r=0;r<t.length;r++){var o=t[r],i=new c(o.type,o.start,o.end,o.sequence,o.descriptor);n.push(i)}return n.sort(function(e,t){return e.sequence-t.sequence})};var u=/\W*Blazor:[^{]*(.*)$/;function l(e){var t=e.currentElement;if(t&&t.nodeType===Node.COMMENT_NODE&&t.textContent){var n=new RegExp(u).exec(t.textContent),r=n&&n[1];if(!r)return;try{return function(e,t,n){var r=JSON.parse(e),o=r.type,i=r.sequence,a=r.descriptor,s=r.prerenderId;if("server"!==o)throw new Error("Invalid component type '"+o+"'.");if(!a)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===i)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(i))throw new Error("Error parsing the sequence '"+i+"' for component '"+e+"'");if(s){var c=function(e,t){for(;t.next()&&t.currentElement;){var n=t.currentElement;if(n.nodeType===Node.COMMENT_NODE&&n.textContent){var r=new RegExp(u).exec(n.textContent),o=r&&r[1];if(o)return f(o,e),n}}return}(s,n);if(!c)throw new Error("Could not find an end component comment for '"+t+"'");return{type:o,sequence:i,descriptor:a,start:t,prerenderId:s,end:c}}return{type:o,sequence:i,descriptor:a,start:t}}(r,t,e)}catch(e){throw new Error("Found malformed component comment at "+t.textContent)}}}function f(e,t){var n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error("Invalid end of component comment: '"+e+"'");var r=n.prerenderId;if(!r)throw new Error("End of component comment must have a value for the prerendered property: '"+e+"'");if(r!==t)throw new Error("End of component comment prerendered property must match the start comment prerender id: '"+t+"', '"+r+"'")}var h=function(){function e(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}return e.prototype.next=function(){return this.currentIndex++,this.currentIndex<this.length?(this.currentElement=this.childNodes[this.currentIndex],!0):(this.currentElement=void 0,!1)},e}()},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=n(16);t.resolveOptions=function(e){var t=r({},i,e);return e&&e.reconnectionOptions&&(t.reconnectionOptions=r({},i.reconnectionOptions,e.reconnectionOptions)),t};var i={configureSignalR:function(e){},logLevel:o.LogLevel.Warning,reconnectionOptions:{maxRetries:5,retryIntervalMilliseconds:3e3,dialogId:"components-reconnect-modal"}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(77),a=n(78),s=n(16),c=function(){function e(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||function(){return window.Blazor.reconnect()}}return e.prototype.onConnectionDown=function(e,t){if(!this._reconnectionDisplay){var n=document.getElementById(e.dialogId);this._reconnectionDisplay=n?new a.UserSpecifiedDisplay(n):new i.DefaultReconnectDisplay(e.dialogId,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new u(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))},e.prototype.onConnectionUp=function(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)},e}();t.DefaultReconnectionHandler=c;var u=function(){function e(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}return e.prototype.dispose=function(){this.isDisposed=!0,this.reconnectDisplay.hide()},e.prototype.attemptPeriodicReconnection=function(e){return r(this,void 0,void 0,function(){var t,n;return o(this,function(r){switch(r.label){case 0:t=0,r.label=1;case 1:return t<e.maxRetries?[4,this.delay(e.retryIntervalMilliseconds)]:[3,7];case 2:if(r.sent(),this.isDisposed)return[3,7];r.label=3;case 3:return r.trys.push([3,5,,6]),[4,this.reconnectCallback()];case 4:return r.sent()?[2]:(this.reconnectDisplay.rejected(),[2]);case 5:return n=r.sent(),this.logger.log(s.LogLevel.Error,n),[3,6];case 6:return t++,[3,1];case 7:return this.reconnectDisplay.failed(),[2]}})})},e.prototype.delay=function(e){return new Promise(function(t){return setTimeout(t,e)})},e}()},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(16),a=function(){function e(e,t,n){var a=this;this.document=t,this.logger=n,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry</button><p>Alternatively, <a href>reload</a></p>',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.button.addEventListener("click",function(){return r(a,void 0,void 0,function(){var e;return o(this,function(t){switch(t.label){case 0:this.show(),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,window.Blazor.reconnect()];case 2:return t.sent()||this.rejected(),[3,4];case 3:return e=t.sent(),this.logger.log(i.LogLevel.Error,e),this.failed(),[3,4];case 4:return[2]}})})}),this.reloadParagraph.querySelector("a").addEventListener("click",function(){return location.reload()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.message.innerHTML="Reconnection failed. Try <a href>reloading</a> the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o<e.byteLength;){var i=0,a=0,s=void 0;do{a|=(127&(s=n[o+i]))<<r[i],i++}while(i<Math.min(5,e.byteLength-o)&&0!=(128&s));if(0!=(128&s)&&i<5)throw new Error("Cannot read message size.");if(5===i&&s>7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s<c.length;s++){var u=c[s],l=this.parseMessage(u,t);l&&o.push(l)}return o},e.prototype.writeMessage=function(e){switch(e.type){case i.MessageType.Invocation:return this.writeInvocation(e);case i.MessageType.StreamInvocation:return this.writeStreamInvocation(e);case i.MessageType.StreamItem:return this.writeStreamItem(e);case i.MessageType.Completion:return this.writeCompletion(e);case i.MessageType.Ping:return a.write(s);case i.MessageType.CancelInvocation:return this.writeCancelInvocation(e);default:throw new Error("Invalid message type.")}},e.prototype.parseMessage=function(e,t){if(0===e.length)throw new Error("Invalid payload.");var n=o().decode(r.Buffer.from(e));if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");var a=n[0];switch(a){case i.MessageType.Invocation:return this.createInvocationMessage(this.readHeaders(n),n);case i.MessageType.StreamItem:return this.createStreamItemMessage(this.readHeaders(n),n);case i.MessageType.Completion:return this.createCompletionMessage(this.readHeaders(n),n);case i.MessageType.Ping:return this.createPingMessage(n);case i.MessageType.Close:return this.createCloseMessage(n);default:return t.log(i.LogLevel.Information,"Unknown message type '"+a+"' ignored."),null}},e.prototype.createCloseMessage=function(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="3.1.0"}]); \ No newline at end of file +var r=n(52),o=n(53),i=n(54);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()<t)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=u.prototype:(null===e&&(e=new u(t)),e.length=t),e}function u(e,t,n){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return f(this,e)}return c(this,e,t,n)}function c(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);u.TYPED_ARRAY_SUPPORT?(e=t).__proto__=u.prototype:e=h(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!u.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|d(t,n),o=(e=a(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(u.isBuffer(t)){var n=0|p(t.length);return 0===(e=a(e,n)).length?e:(t.copy(e,0,0,n),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?a(e,0):h(e,t);if("Buffer"===t.type&&i(t.data))return h(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function l(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function f(e,t){if(l(t),e=a(e,t<0?0:0|p(t)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function h(e,t){var n=t.length<0?0:0|p(t.length);e=a(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function p(e){if(e>=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,s=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(o){var l=-1;for(i=n;i<a;i++)if(c(e,i)===c(t,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===u)return l*s}else-1!==l&&(i-=i-l),l=-1}else for(n+u>a&&(n=a-u),i=n;i>=0;i--){for(var f=!0,h=0;h<u;h++)if(c(e,i+h)!==c(t,h)){f=!1;break}if(f)return i}return-1}function b(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;s<r;++s){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))return s;e[n+s]=a}return s}function m(e,t,n,r){return q(F(t,e.length-n),e,n,r)}function w(e,t,n,r){return q(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function E(e,t,n,r){return w(e,t,n,r)}function S(e,t,n,r){return q(H(t),e,n,r)}function _(e,t,n,r){return q(function(e,t){for(var n,r,o,i=[],s=0;s<e.length&&!((t-=2)<0);++s)n=e.charCodeAt(s),r=n>>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function C(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o<n;){var i,s,a,u,c=e[o],l=null,f=c>239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],s=e[o+2],128==(192&i)&&128==(192&s)&&(u=(15&c)<<12|(63&i)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],s=e[o+2],a=e[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=I)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=I));return n}(r)}t.Buffer=u,t.SlowBuffer=function(e){+e!=e&&(e=0);return u.alloc(+e)},t.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=s(),u.poolSize=8192,u._augment=function(e){return e.__proto__=u.prototype,e},u.from=function(e,t,n){return c(null,e,t,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(e,t,n){return function(e,t,n,r){return l(t),t<=0?a(e,t):void 0!==n?"string"==typeof r?a(e,t).fill(n,r):a(e,t).fill(n):a(e,t)}(null,e,t,n)},u.allocUnsafe=function(e){return f(null,e)},u.allocUnsafeSlow=function(e){return f(null,e)},u.isBuffer=function(e){return!(null==e||!e._isBuffer)},u.compare=function(e,t){if(!u.isBuffer(e)||!u.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0},u.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(e,t){if(!i(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return u.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=u.allocUnsafe(t),o=0;for(n=0;n<e.length;++n){var s=e[n];if(!u.isBuffer(s))throw new TypeError('"list" argument must be an Array of Buffers');s.copy(r,o),o+=s.length}return r},u.byteLength=d,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)g(this,t,t+1);return this},u.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)g(this,t,t+3),g(this,t+1,t+2);return this},u.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)g(this,t,t+7),g(this,t+1,t+6),g(this,t+2,t+5),g(this,t+3,t+4);return this},u.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?C(this,0,e):function(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),"<Buffer "+e+">"},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),s=(n>>>=0)-(t>>>=0),a=Math.min(i,s),c=this.slice(r,o),l=e.slice(t,n),f=0;f<a;++f)if(c[f]!==l[f]){i=c[f],s=l[f];break}return i<s?-1:s<i?1:0},u.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},u.prototype.indexOf=function(e,t,n){return y(this,e,t,n,!0)},u.prototype.lastIndexOf=function(e,t,n){return y(this,e,t,n,!1)},u.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var I=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(127&e[o]);return r}function P(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(e[o]);return r}function R(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=t;i<n;++i)o+=N(e[i]);return o}function x(e,t,n){for(var r=e.slice(t,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function A(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function D(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||t<i)throw new RangeError('"value" argument is out of bounds');if(n+r>e.length)throw new RangeError("Index out of range")}function O(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o<i;++o)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o<i;++o)e[n+o]=t>>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),u.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=u.prototype;else{var o=t-e;n=new u(o,void 0);for(var i=0;i<o;++i)n[i]=this[i+e]}return n},u.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r},u.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e+--t],o=1;t>0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||A(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||A(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||A(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||A(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||A(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r>=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||A(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||A(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||A(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||A(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||A(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i<n&&(o*=256);)this[t+i]=e/o&255;return t+n},u.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=n-1,i=1;for(this[t+o]=255&e;--o>=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=0,s=1,a=0;for(this[t]=255&e;++i<n&&(s*=256);)e<0&&0===a&&0!==this[t+i-1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=n-1,s=1,a=0;for(this[t+i]=255&e;--i>=0&&(s*=256);)e<0&&0===a&&0!==this[t+i+1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var o,i=r-n;if(this===e&&n<t&&t<r)for(o=i-1;o>=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)e[o+t]=this[o+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+i),t);return i},u.prototype.fill=function(e,t,n,r){if("string"==typeof e){if("string"==typeof t?(r=t,t=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===e.length){var o=e.charCodeAt(0);o<256&&(e=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!u.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError("Out of range index");if(n<=t)return this;var i;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i<n;++i)this[i]=e;else{var s=u.isBuffer(e)?e:F(new u(e,r).toString()),a=s.length;for(i=0;i<n-t;++i)this[i+t]=s[i%a]}return this};var j=/[^+\/0-9A-Za-z-_]/g;function N(e){return e<16?"0"+e.toString(16):e.toString(16)}function F(e,t){var n;t=t||1/0;for(var r=e.length,o=null,i=[],s=0;s<r;++s){if((n=e.charCodeAt(s))>55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(j,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o<r&&!(o+n>=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(12))},function(e,t,n){(function(e){var r=Object.getOwnPropertyDescriptors||function(e){for(var t=Object.keys(e),n={},r=0;r<t.length;r++)n[t[r]]=Object.getOwnPropertyDescriptor(e,t[r]);return n},o=/%[sdj%]/g;t.format=function(e){if(!v(e)){for(var t=[],n=0;n<arguments.length;n++)t.push(a(arguments[n]));return t.join(" ")}n=1;for(var r=arguments,i=r.length,s=String(e).replace(o,function(e){if("%%"===e)return"%";if(n>=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),u=r[n];n<i;u=r[++n])g(u)||!w(u)?s+=" "+u:s+=" "+a(u);return s},t.deprecate=function(n,r){if(void 0!==e&&!0===e.noDeprecation)return n;if(void 0===e)return function(){return t.deprecate(n,r).apply(this,arguments)};var o=!1;return function(){if(!o){if(e.throwDeprecation)throw new Error(r);e.traceDeprecation?console.trace(r):console.error(r),o=!0}return n.apply(this,arguments)}};var i,s={};function a(e,n){var r={seen:[],stylize:c};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=u),l(r,e,r.depth)}function u(e,t){var n=a.styles[t];return n?"["+a.colors[n][0]+"m"+e+"["+a.colors[n][1]+"m":e}function c(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&_(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var s=Object.keys(n),a=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(n)),S(n)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(n);if(0===s.length){if(_(n)){var u=n.name?": "+n.name:"";return e.stylize("[Function"+u+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var c,w="",T=!1,C=["{","}"];(p(n)&&(T=!0,C=["[","]"]),_(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==s.length||T&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),c=T?function(e,t,n,r,o){for(var i=[],s=0,a=t.length;s<a;++s)k(t,String(s))?i.push(h(e,t,n,r,String(s),!0)):i.push("");return o.forEach(function(o){o.match(/^\d+$/)||i.push(h(e,t,n,r,o,!0))}),i}(e,n,r,a,s):s.map(function(t){return h(e,n,r,a,t,T)}),e.seen.pop(),function(e,t,n){if(e.reduce(function(e,t){return 0,t.indexOf("\n")>=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(c,w,C)):C[0]+w+C[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var s,a,u;if((u=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?a=u.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):u.set&&(a=e.stylize("[Setter]","special")),k(r,o)||(s="["+o+"]"),a||(e.seen.indexOf(u.value)<0?(a=g(n)?l(e,u.value,null):l(e,u.value,n-1)).indexOf("\n")>-1&&(a=i?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n")):a=e.stylize("[Circular]","special")),b(s)){if(i&&o.match(/^\d+$/))return a;(s=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===T(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===T(e)}function S(e){return w(e)&&("[object Error]"===T(e)||e instanceof Error)}function _(e){return"function"==typeof e}function T(e){return Object.prototype.toString.call(e)}function C(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!s[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;s[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else s[n]=function(){};return s[n]},t.inspect=a,a.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},a.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=_,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(60);var I=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[C(e.getHours()),C(e.getMinutes()),C(e.getSeconds())].join(":"),[e.getDate(),I[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(61),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function R(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i<arguments.length;i++)o.push(arguments[i]);o.push(function(e,r){e?n(e):t(r)});try{e.apply(this,o)}catch(e){n(e)}return r}return Object.setPrototypeOf(t,Object.getPrototypeOf(e)),P&&Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),Object.defineProperties(t,r(e))},t.promisify.custom=P,t.callbackify=function(t){if("function"!=typeof t)throw new TypeError('The "original" argument must be of type Function');function n(){for(var n=[],r=0;r<arguments.length;r++)n.push(arguments[r]);var o=n.pop();if("function"!=typeof o)throw new TypeError("The last argument must be of type Function");var i=this,s=function(){return o.apply(i,arguments)};t.apply(this,n).then(function(t){e.nextTick(s,null,t)},function(t){e.nextTick(R,t,s)})}return Object.setPrototypeOf(n,Object.getPrototypeOf(t)),Object.defineProperties(n,r(t)),n}}).call(this,n(59))},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";(function(t,r){var o=n(22);e.exports=m;var i,s=n(63);m.ReadableState=b;n(39).EventEmitter;var a=function(e,t){return e.listeners(t).length},u=n(40),c=n(13).Buffer,l=t.Uint8Array||function(){};var f=n(19);f.inherits=n(14);var h=n(64),p=void 0;p=h&&h.debuglog?h.debuglog("stream"):function(){};var d,g=n(65),y=n(41);f.inherits(m,u);var v=["error","close","destroy","pause","resume"];function b(e,t){e=e||{};var r=t instanceof(i=i||n(8));this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var o=e.highWaterMark,s=e.readableHighWaterMark,a=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(s||0===s)?s:a,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new g,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(d||(d=n(42).StringDecoder),this.decoder=new d(e.encoding),this.encoding=e.encoding)}function m(e){if(i=i||n(8),!(this instanceof m))return new m(e);this._readableState=new b(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),u.call(this)}function w(e,t,n,r,o){var i,s=e._readableState;null===t?(s.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,T(e)}(e,s)):(o||(i=function(e,t){var n;r=t,c.isBuffer(r)||r instanceof l||"string"==typeof t||void 0===t||e.objectMode||(n=new TypeError("Invalid non-string/buffer chunk"));var r;return n}(s,t)),i?e.emit("error",i):s.objectMode||t&&t.length>0?("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?s.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,s,t,!0):s.ended?e.emit("error",new Error("stream.push() after EOF")):(s.reading=!1,s.decoder&&!n?(t=s.decoder.write(t),s.objectMode||0!==t.length?E(e,s,t,!1):I(e,s)):E(e,s,t,!1))):r||(s.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(s)}function E(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(e.emit("data",n),e.read(0)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&T(e)),I(e,t)}Object.defineProperty(m.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),m.prototype.destroy=y.destroy,m.prototype._undestroy=y.undestroy,m.prototype._destroy=function(e,t){this.push(null),t(e)},m.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=c.from(e,t),t=""),n=!0),w(this,e,t,!1,n)},m.prototype.unshift=function(e){return w(this,e,null,!0,!1)},m.prototype.isPaused=function(){return!1===this._readableState.flowing},m.prototype.setEncoding=function(e){return d||(d=n(42).StringDecoder),this._readableState.decoder=new d(e),this._readableState.encoding=e,this};var S=8388608;function _(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function T(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(C,e):C(e))}function C(e){p("emit readable"),e.emit("readable"),x(e)}function I(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(p("maybeReadMore read 0"),e.read(0),n!==t.length);)n=t.length;t.readingMore=!1}function P(e){p("readable nexttick read 0"),e.read(0)}function R(e,t){t.reading||(p("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),x(e),t.flowing&&!t.reading&&e.read(0)}function x(e){var t=e._readableState;for(p("flow",t.flowing);t.flowing&&null!==e.read(););}function A(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;e<t.head.data.length?(r=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):r=e===t.head.data.length?t.shift():n?function(e,t){var n=t.head,r=1,o=n.data;e-=o.length;for(;n=n.next;){var i=n.data,s=e>i.length?i.length:e;if(s===i.length?o+=i:o+=i.slice(0,e),0===(e-=s)){s===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(s));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,s=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,s),0===(e-=s)){s===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(s));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function D(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(O,t,e))}function O(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function L(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}m.prototype.read=function(e){p("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?D(this):T(this),null;if(0===(e=_(e,t))&&t.ended)return 0===t.length&&D(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e<t.highWaterMark)&&p("length less than watermark",o=!0),t.ended||t.reading?p("reading or ended",o=!1):o&&(p("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=_(n,t))),null===(r=e>0?A(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&D(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function c(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",c),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(u):n.once("end",u),e.on("unpipe",c);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,x(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==L(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===a(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?s(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<o;i++)r[i].emit("unpipe",this,n);return this}var s=L(t.pipes,e);return-1===s?this:(t.pipes.splice(s,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n),this)},m.prototype.on=function(e,t){var n=u.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var r=this._readableState;r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.emittedReadable=!1,r.reading?r.length&&T(this):o.nextTick(P,this))}return n},m.prototype.addListener=m.prototype.on,m.prototype.resume=function(){var e=this._readableState;return e.flowing||(p("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,o.nextTick(R,e,t))}(this,e)),this},m.prototype.pause=function(){return p("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(p("pause"),this._readableState.flowing=!1,this.emit("pause")),this},m.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var o in e.on("end",function(){if(p("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)}),e.on("data",function(o){(p("wrapped data"),n.decoder&&(o=n.decoder.write(o)),n.objectMode&&null==o)||(n.objectMode||o&&o.length)&&(t.push(o)||(r=!0,e.pause()))}),e)void 0===this[o]&&"function"==typeof e[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));for(var i=0;i<v.length;i++)e.on(v[i],this.emit.bind(this,v[i]));return this._read=function(t){p("wrapped _read",t),r&&(r=!1,e.resume())},this},Object.defineProperty(m.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),m._fromList=A}).call(this,n(12),n(23))},function(e,t,n){"use strict";var r,o="object"==typeof Reflect?Reflect:null,i=o&&"function"==typeof o.apply?o.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=o&&"function"==typeof o.ownKeys?o.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var s=Number.isNaN||function(e){return e!=e};function a(){a.init.call(this)}e.exports=a,a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var u=10;function c(e){return void 0===e._maxListeners?a.defaultMaxListeners:e._maxListeners}function l(e,t,n,r){var o,i,s,a;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),s=i[t]),void 0===s)s=i[t]=n,++e._eventsCount;else if("function"==typeof s?s=i[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(o=c(e))>0&&s.length>o&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=s.length,a=u,console&&console.warn&&console.warn(a)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t<arguments.length;t++)e.push(arguments[t]);this.fired||(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,i(this.listener,this.target,e))}.bind(r);return o.listener=n,r.wrapFn=o,o}function h(e,t,n){var r=e._events;if(void 0===r)return[];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(o):d(o,o.length)}function p(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}Object.defineProperty(a,"defaultMaxListeners",{enumerable:!0,get:function(){return u},set:function(e){if("number"!=typeof e||e<0||s(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");u=e}}),a.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},a.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||s(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},a.prototype.getMaxListeners=function(){return c(this)},a.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,o=this._events;if(void 0!==o)r=r&&void 0===o.error;else if(!r)return!1;if(r){var s;if(t.length>0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var u=o[e];if(void 0===u)return!1;if("function"==typeof u)i(u,this,t);else{var c=u.length,l=d(u,c);for(n=0;n<c;++n)i(l[n],this,t)}return!0},a.prototype.addListener=function(e,t){return l(this,e,t,!1)},a.prototype.on=a.prototype.addListener,a.prototype.prependListener=function(e,t){return l(this,e,t,!0)},a.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.on(e,f(this,e,t)),this},a.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.prependListener(e,f(this,e,t)),this},a.prototype.removeListener=function(e,t){var n,r,o,i,s;if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);if(void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(o=-1,i=n.length-1;i>=0;i--)if(n[i]===t||n[i].listener===t){s=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(n,o),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,s||t)}return this},a.prototype.off=a.prototype.removeListener,a.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var o,i=Object.keys(n);for(r=0;r<i.length;++r)"removeListener"!==(o=i[r])&&this.removeAllListeners(o);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},a.prototype.listeners=function(e){return h(this,e,!0)},a.prototype.rawListeners=function(e){return h(this,e,!1)},a.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},a.prototype.listenerCount=p,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(39).EventEmitter},function(e,t,n){"use strict";var r=n(22);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return i||s?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(67).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},i.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},i.prototype.text=function(e,t){var n=function(e,t,n){var r=t.length-1;if(r<n)return 0;var o=s(t[r]);if(o>=0)return o>0&&(e.lastNeed=o-1),o;if(--r<n||-2===o)return 0;if((o=s(t[r]))>=0)return o>0&&(e.lastNeed=o-2),o;if(--r<n||-2===o)return 0;if((o=s(t[r]))>=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(22);function s(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var a,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var c=n(19);c.inherits=n(14);var l={deprecate:n(70)},f=n(40),h=n(13).Buffer,p=o.Uint8Array||function(){};var d,g=n(41);function y(){}function v(e,t){a=a||n(8),e=e||{};var r=t instanceof a;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(T,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),T(e,t))}(e,n,r,t,o);else{var s=S(n);s||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?u(w,e,n,s,o):w(e,n,s,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new s(this)}function b(e){if(a=a||n(8),!(d.call(b,this)||this instanceof a))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,s){t.writelen=r,t.writecb=s,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var a=0,u=!0;n;)o[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;o.allBuffers=u,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new s(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:c.length,c,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function _(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),T(e,t)})}function T(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(_,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,s=!1,a=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return a&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(a||function(e,t,n,r){var o=!0,s=!1;return null===n?s=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),i.nextTick(r,s),o=!1),o}(this,o,e,n))&&(o.pendingcb++,s=function(e,t,n,r,o,i){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==s&&(n=!0,o="buffer",r=s)}var a=t.objectMode?1:r.length;t.length+=a;var u=t.length<t.highWaterMark;u||(t.needDrain=!0);if(t.writing||t.corked){var c=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:o,isBuf:n,callback:i,next:null},c?c.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else m(e,t,!1,a,r,o,i);return u}(this,o,a,e,t,n)),s},b.prototype.cork=function(){this._writableState.corked++},b.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||E(this,e))},b.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(23),n(68).setImmediate,n(12))},function(e,t,n){"use strict";e.exports=s;var r=n(8),o=n(19);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}function s(e){if(!(this instanceof s))return new s(e);r.call(this,e),this._transformState={afterTransform:i.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",a)}function a(){var e=this;"function"==typeof this._flush?this._flush(function(t,n){u(e,t,n)}):u(this,null,null)}function u(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new Error("Calling transform done when ws.length != 0");if(e._transformState.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}o.inherits=n(14),o.inherits(s,r),s.prototype.push=function(e,t){return this._transformState.needTransform=!1,r.prototype.push.call(this,e,t)},s.prototype._transform=function(e,t,n){throw new Error("_transform() is not implemented")},s.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var o=this._readableState;(r.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},s.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},s.prototype._destroy=function(e,t){var n=this;r.prototype._destroy.call(this,e,function(e){t(e),n.emit("close")})}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return h});var r,o,i=n(3),s=n(4),a=n(0),u=n(1),c=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e};if("undefined"==typeof XMLHttpRequest){var f=require;o=f("request")}var h=function(t){function n(e){var n=t.call(this)||this;if(void 0===o)throw new Error("The 'request' module could not be loaded.");return n.logger=e,n.cookieJar=o.jar(),n.request=o.defaults({jar:n.cookieJar}),n}return c(n,t),n.prototype.send=function(t){var n=this;return new Promise(function(r,o){var c;c=Object(u.g)(t.content)?e.from(t.content):t.content||"";var f=n.request(t.url,{body:c,encoding:"arraybuffer"===t.responseType?null:"utf8",headers:l({"X-Requested-With":"XMLHttpRequest"},t.headers),method:t.method,timeout:t.timeout},function(e,u,c){if(t.abortSignal&&(t.abortSignal.onabort=null),e)return"ETIMEDOUT"===e.code&&(n.logger.log(a.a.Warning,"Timeout from HTTP request."),o(new i.c)),n.logger.log(a.a.Warning,"Error from HTTP request. "+e),void o(e);u.statusCode>=200&&u.statusCode<300?r(new s.b(u.statusCode,u.statusMessage||"",c)):o(new i.b(u.statusMessage||"",u.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(s.a)}).call(this,n(35).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(7),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var s=new Uint8Array(t);if(-1===(u=s.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var a=u+1;n=String.fromCharCode.apply(null,s.slice(0,a)),i=s.byteLength>a?s.slice(a).buffer:null}else{var u,c=t;if(-1===(u=c.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");a=u+1;n=c.substring(0,a),i=c.length>a?c.substring(a):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(35).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},i=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)s.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return s},s=this&&this.__spread||function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(i(arguments[t]));return e};Object.defineProperty(t,"__esModule",{value:!0}),n(16),n(24);var a=n(2),u=n(85),c=n(33),l=n(34),f=n(76),h=n(79),p=n(15),d=n(80),g=n(18),y=n(81),v=n(82),b=n(5),m=!1,w=!1;function E(e){return r(this,void 0,void 0,function(){var t,n,i,s,a,u,c=this;return o(this,function(l){switch(l.label){case 0:if(w)throw new Error("Blazor has already started.");return w=!0,t=y.resolveOptions(e),n=new h.ConsoleLogger(t.logLevel),window.Blazor.defaultReconnectionHandler=new v.DefaultReconnectionHandler(n),t.reconnectionHandler=t.reconnectionHandler||window.Blazor.defaultReconnectionHandler,n.log(p.LogLevel.Information,"Starting up blazor server-side application."),i=d.discoverComponents(document),s=new d.CircuitDescriptor(i),[4,S(t,n,s)];case 1:return a=l.sent(),[4,s.startCircuit(a)];case 2:return l.sent()?(u=function(e){return r(c,void 0,void 0,function(){var r,i;return o(this,function(o){switch(o.label){case 0:return m?[2,!1]:(i=e)?[3,2]:[4,S(t,n,s)];case 1:i=o.sent(),o.label=2;case 2:return r=i,[4,s.reconnect(r)];case 3:return o.sent()?(t.reconnectionHandler.onConnectionUp(),[2,!0]):(n.log(p.LogLevel.Information,"Reconnection attempt to the circuit was rejected by the server. This may indicate that the associated state is no longer available on the server."),[2,!1])}})})},window.addEventListener("unload",function(){var e=new FormData,t=s.circuitId;e.append("circuitId",t),navigator.sendBeacon("_blazor/disconnect",e)},!1),window.Blazor.reconnect=u,n.log(p.LogLevel.Information,"Blazor server-side application started."),[2]):(n.log(p.LogLevel.Error,"Failed to start the circuit."),[2])}})})}function S(e,t,n){return r(this,void 0,void 0,function(){var r,i,l,h,d;return o(this,function(o){switch(o.label){case 0:(r=new u.MessagePackHubProtocol).name="blazorpack",i=(new a.HubConnectionBuilder).withUrl("_blazor").withHubProtocol(r),e.configureSignalR(i),l=i.build(),g.setEventDispatcher(function(e,t){return l.send("DispatchBrowserEvent",JSON.stringify(e),JSON.stringify(t))}),window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return l.send("OnLocationChanged",e,t)}),l.on("JS.AttachComponent",function(e,t){return b.attachRootComponentToLogicalElement(0,n.resolveElement(t),e)}),l.on("JS.BeginInvokeJS",DotNet.jsCallDispatcher.beginInvokeJSFromDotNet),l.on("JS.EndInvokeDotNet",function(e){var t;return(t=DotNet.jsCallDispatcher).endInvokeDotNetFromJS.apply(t,s(JSON.parse(e)))}),h=f.RenderQueue.getOrCreate(t),l.on("JS.RenderBatch",function(e,n){t.log(p.LogLevel.Debug,"Received render batch with id "+e+" and "+n.byteLength+" bytes."),h.processBatch(e,n,l)}),l.onclose(function(t){return!m&&e.reconnectionHandler.onConnectionDown(e.reconnectionOptions,t)}),l.on("JS.Error",function(e){m=!0,_(l,e,t),c.showErrorNotification()}),window.Blazor._internal.forceCloseConnection=function(){return l.stop()},o.label=1;case 1:return o.trys.push([1,3,,4]),[4,l.start()];case 2:return o.sent(),[3,4];case 3:return d=o.sent(),_(l,d,t),[3,4];case 4:return DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,t,n,r,o){l.send("BeginInvokeDotNetFromJS",e?e.toString():null,t,n,r||0,o)},endInvokeJSFromDotNet:function(e,t,n){l.send("EndInvokeJSFromDotNet",e,t,n)}}),[2,l]}})})}function _(e,t,n){n.log(p.LogLevel.Error,t),e&&e.stop()}window.Blazor.start=E,l.shouldAutoStart()&&E()},function(e,t,n){"use strict";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=c(e),r=n[0],s=n[1],a=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,s)),u=0,l=s>0?r-4:r,f=0;f<l;f+=4)t=o[e.charCodeAt(f)]<<18|o[e.charCodeAt(f+1)]<<12|o[e.charCodeAt(f+2)]<<6|o[e.charCodeAt(f+3)],a[u++]=t>>16&255,a[u++]=t>>8&255,a[u++]=255&t;2===s&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,a[u++]=255&t);1===s&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,a[u++]=t>>8&255,a[u++]=255&t);return a},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],s=0,a=n-o;s<a;s+=16383)i.push(l(e,s,s+16383>a?a:s+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a<u;++a)r[a]=s[a],o[s.charCodeAt(a)]=a;function c(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,s=[],a=t;a<n;a+=3)o=(e[a]<<16&16711680)+(e[a+1]<<8&65280)+(255&e[a+2]),s.push(r[(i=o)>>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,s,a=8*o-r-1,u=(1<<a)-1,c=u>>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=a;l>0;i=256*i+e[t+f],f+=h,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,r),i-=c}return(p?-1:1)*s*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var s,a,u,c=8*i-o-1,l=(1<<c)-1,f=l>>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),(t+=s+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(s++,u/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*u-1)*Math.pow(2,o),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;e[n+p]=255&a,p+=d,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[n+p]=255&s,p+=d,s/=256,c-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=c(e),r=n[0],s=n[1],a=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,s)),u=0,l=s>0?r-4:r,f=0;f<l;f+=4)t=o[e.charCodeAt(f)]<<18|o[e.charCodeAt(f+1)]<<12|o[e.charCodeAt(f+2)]<<6|o[e.charCodeAt(f+3)],a[u++]=t>>16&255,a[u++]=t>>8&255,a[u++]=255&t;2===s&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,a[u++]=255&t);1===s&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,a[u++]=t>>8&255,a[u++]=255&t);return a},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],s=0,a=n-o;s<a;s+=16383)i.push(l(e,s,s+16383>a?a:s+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a<u;++a)r[a]=s[a],o[s.charCodeAt(a)]=a;function c(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,s=[],a=t;a<n;a+=3)o=(e[a]<<16&16711680)+(e[a+1]<<8&65280)+(255&e[a+2]),s.push(r[(i=o)>>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,s,a=8*o-r-1,u=(1<<a)-1,c=u>>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=a;l>0;i=256*i+e[t+f],f+=h,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,r),i-=c}return(p?-1:1)*s*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var s,a,u,c=8*i-o-1,l=(1<<c)-1,f=l>>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),(t+=s+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(s++,u/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*u-1)*Math.pow(2,o),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;e[n+p]=255&a,p+=d,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[n+p]=255&s,p+=d,s/=256,c-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ +function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0}function o(e){return t.Buffer&&"function"==typeof t.Buffer.isBuffer?t.Buffer.isBuffer(e):!(null==e||!e._isBuffer)}var i=n(36),s=Object.prototype.hasOwnProperty,a=Array.prototype.slice,u="foo"===function(){}.name;function c(e){return Object.prototype.toString.call(e)}function l(e){return!o(e)&&("function"==typeof t.ArrayBuffer&&("function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(e):!!e&&(e instanceof DataView||!!(e.buffer&&e.buffer instanceof ArrayBuffer))))}var f=e.exports=v,h=/\s*function\s+([^\(\s]*)\s*/;function p(e){if(i.isFunction(e)){if(u)return e.name;var t=e.toString().match(h);return t&&t[1]}}function d(e,t){return"string"==typeof e?e.length<t?e:e.slice(0,t):e}function g(e){if(u||!i.isFunction(e))return i.inspect(e);var t=p(e);return"[Function"+(t?": "+t:"")+"]"}function y(e,t,n,r,o){throw new f.AssertionError({message:n,actual:e,expected:t,operator:r,stackStartFunction:o})}function v(e,t){e||y(e,!0,t,"==",f.ok)}function b(e,t,n,s){if(e===t)return!0;if(o(e)&&o(t))return 0===r(e,t);if(i.isDate(e)&&i.isDate(t))return e.getTime()===t.getTime();if(i.isRegExp(e)&&i.isRegExp(t))return e.source===t.source&&e.global===t.global&&e.multiline===t.multiline&&e.lastIndex===t.lastIndex&&e.ignoreCase===t.ignoreCase;if(null!==e&&"object"==typeof e||null!==t&&"object"==typeof t){if(l(e)&&l(t)&&c(e)===c(t)&&!(e instanceof Float32Array||e instanceof Float64Array))return 0===r(new Uint8Array(e.buffer),new Uint8Array(t.buffer));if(o(e)!==o(t))return!1;var u=(s=s||{actual:[],expected:[]}).actual.indexOf(e);return-1!==u&&u===s.expected.indexOf(t)||(s.actual.push(e),s.expected.push(t),function(e,t,n,r){if(null==e||null==t)return!1;if(i.isPrimitive(e)||i.isPrimitive(t))return e===t;if(n&&Object.getPrototypeOf(e)!==Object.getPrototypeOf(t))return!1;var o=m(e),s=m(t);if(o&&!s||!o&&s)return!1;if(o)return e=a.call(e),t=a.call(t),b(e,t,n);var u,c,l=S(e),f=S(t);if(l.length!==f.length)return!1;for(l.sort(),f.sort(),c=l.length-1;c>=0;c--)if(l[c]!==f[c])return!1;for(c=l.length-1;c>=0;c--)if(u=l[c],!b(e[u],t[u],n,r))return!1;return!0}(e,t,n,s))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var s="string"==typeof r,a=!e&&o&&!n;if((!e&&i.isError(o)&&s&&w(o,n)||a)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),s=o.indexOf("\n"+i);if(s>=0){var a=o.indexOf("\n",s+1);o=o.substring(a+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)s.call(e,n)&&t.push(n);return t}}).call(this,n(37))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:s}catch(e){r=s}}();var u,c=[],l=!1,f=-1;function h(){l&&u&&(l=!1,u.length?c=u.concat(c):f=-1,c.length&&p())}function p(){if(!l){var e=a(h);l=!0;for(var t=c.length;t;){for(u=c,c=[];++f<t;)u&&u[f].run();f=-1,t=c.length}u=null,l=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===s||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function d(e,t){this.fun=e,this.array=t}function g(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new d(e,t)),1!==c.length||l||a(p)},d.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=g,o.addListener=g,o.once=g,o.off=g,o.removeListener=g,o.removeAllListeners=g,o.emit=g,o.prependListener=g,o.prependOnceListener=g,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(8)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(13).Buffer,o=n(66);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,n=i,o=a,t.copy(n,o),a+=s.data.length,s=s.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(20),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=s),i(o,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(69),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(12))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,s,a,u=1,c={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(s="setImmediate$"+Math.random()+"$",a=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(s)&&d(+t.data.slice(s.length))},e.addEventListener?e.addEventListener("message",a,!1):e.attachEvent("onmessage",a),r=function(t){e.postMessage(s+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return c[u]=o,r(u),u++},h.clearImmediate=p}function p(e){delete c[e]}function d(e){if(l)setTimeout(d,0,e);else{var t=c[e];if(t){l=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{p(e),l=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(12),n(23))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(12))},function(e,t,n){"use strict";var r=n(72).Transform,o=n(14),i=n(21);function s(e){(e=e||{}).objectMode=!0,e.highWaterMark=16,r.call(this,e),this._msgpack=e.msgpack}function a(e){if(!(this instanceof a))return(e=e||{}).msgpack=this,new a(e);s.call(this,e)}function u(e){if(!(this instanceof u))return(e=e||{}).msgpack=this,new u(e);s.call(this,e),this._chunks=i()}o(s,r),o(a,s),a.prototype._transform=function(e,t,n){var r=null;try{r=this._msgpack.encode(e).slice(0)}catch(e){return this.emit("error",e),n()}this.push(r),n()},o(u,s),u.prototype._transform=function(e,t,n){e&&this._chunks.append(e);try{var r=this._msgpack.decode(this._chunks);this.push(r)}catch(e){return void(e instanceof this._msgpack.IncompleteBufferError?n():this.emit("error",e))}this._chunks.length>0?this._transform(null,t,n):n()},e.exports.decoder=u,e.exports.encoder=a},function(e,t,n){(t=e.exports=n(38)).Stream=t,t.Readable=t,t.Writable=n(43),t.Duplex=n(8),t.Transform=n(44),t.PassThrough=n(73)},function(e,t,n){"use strict";e.exports=i;var r=n(44),o=n(19);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(14),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(21);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(36).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t<n)}(h,o))return null;switch(h){case 192:return n(null,1);case 194:return n(!1,1);case 195:return n(!0,1);case 204:return n(p=e.readUInt8(r+1),2);case 205:return n(p=e.readUInt16BE(r+1),3);case 206:return n(p=e.readUInt32BE(r+1),5);case 207:for(f=7;f>=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var s=e.readUInt32BE(t+0),a=e.readUInt32BE(t+4);return(4294967296*s+a)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),s(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),s(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),a(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return u(e,r,1);case 213:return u(e,r,2);case 214:return u(e,r,4);case 215:return u(e,r,8);case 216:return u(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?c(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?c(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?c(e,r,l,i,6):null}if(144==(240&h))return s(e,r,i=15&h,1);if(128==(240&h))return a(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function s(e,t,r,o){var s,a=[],u=0;for(t+=o,s=0;s<r;s++){var c=i(e,t);if(!c)return null;a.push(c.value),t+=c.bytesConsumed,u+=c.bytesConsumed}return n(a,o+u)}function a(e,t,r,o){var s,a={},u=0;for(t+=o,s=0;s<r;s++){var c=i(e,t);if(!c)return null;var l=i(e,t+=c.bytesConsumed);if(!l)return null;a[c.value]=l.value,t+=l.bytesConsumed,u+=c.bytesConsumed+l.bytesConsumed}return n(a,o+u)}function u(e,t,n){var r=e.readInt8(t+1);return c(e,t,r,n,2)}function c(t,r,o,i,s){var a,u;if(r+=s,o<0)switch(o){case-1:return function(e,t,r){var o,i;switch(i=0,t){case 4:o=e.readUInt32BE(0);break;case 8:var s=e.readUInt32BE(0),a=e.readUInt32BE(4);i=s/4,o=(3&s)*Math.pow(2,32)+a;break;case 12:throw new Error("timestamp 96 is not yet implemented")}var u=1e3*o+Math.round(i/1e6);return n(new Date(u),t+r)}(u=t.slice(r,r+i),i,s)}for(a=0;a<e.length;a++){if(o===e[a].type)return u=t.slice(r,r+i),n(e[a].decode(u),s+i)}throw new Error("unable to find ext type "+o)}},e.exports.IncompleteBufferError=o},function(e,t,n){"use strict";var r=n(13).Buffer,o=n(21),i=.1;function s(e,t){var n;return(n=r.allocUnsafe(5))[0]=202,n.writeFloatBE(e,1),(t||Math.abs(e-n.readFloatBE(1))>i)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function a(u,c){var l,f,h;if(void 0===u)throw new Error("undefined is not encodable in msgpack!");if(null===u)(l=r.allocUnsafe(1))[0]=192;else if(!0===u)(l=r.allocUnsafe(1))[0]=195;else if(!1===u)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof u)(f=r.byteLength(u))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(u,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(u,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(u,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(u,5));else if(u&&(u.readUInt32LE||u instanceof Uint8Array))u instanceof Uint8Array&&(u=r.from(u)),u.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=u.length):u.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(u.length,1)),l=o([l,u]);else if(Array.isArray(u))u.length<16?(l=r.allocUnsafe(1))[0]=144|u.length:u.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(u.length,1)),l=u.reduce(function(e,t){return e.append(a(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof u.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),s=1e6*(n-1e3*i);if(s||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var a=4*s,u=i/Math.pow(2,32),c=a+u&4294967295,l=4294967295&i;t.writeInt32BE(c,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(u);if("object"==typeof u)l=function(t){var n,i,s=-1,a=[];for(n=0;n<e.length;n++)if(e[n].check(t)){i=e[n].encode(t);break}if(!i)return null;1==(s=i.length-1)?a.push(212):2===s?a.push(213):4===s?a.push(214):8===s?a.push(215):16===s?a.push(216):s<256?(a.push(199),a.push(s)):s<65536?(a.push(200),a.push(s>>8),a.push(255&s)):(a.push(201),a.push(s>>24),a.push(s>>16&255),a.push(s>>8&255),a.push(255&s));return o().append(r.from(a)).append(i)}(u)||function(e){var t,n,i=[],s=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++s,i.push(a(t,!0)),i.push(a(e[t],!0)));s<16?(n=r.allocUnsafe(1))[0]=128|s:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(s,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(u);else if("number"==typeof u){if((h=u)!==Math.floor(h))return s(u,t);if(u>=0)if(u<128)(l=r.allocUnsafe(1))[0]=u;else if(u<256)(l=r.allocUnsafe(2))[0]=204,l[1]=u;else if(u<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(u,1);else if(u<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(u,1);else{if(!(u<=9007199254740991))return s(u,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,u)}else if(u>=-32)(l=r.allocUnsafe(1))[0]=256+u;else if(u>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(u,1);else if(u>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(u,1);else if(u>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(u,1);else{if(!(u>=-9007199254740991))return s(u,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var s=1,a=t+7;a>=t;a--){var u=(255^e[a])+s;e[a]=255&u,s=u>>8}}(l,1,u)}}}if(!l)throw new Error("not implemented yet");return c?l:l.slice()}return a}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(5),s=n(77),a=n(15),u=function(){function e(e,t){this.nextBatchId=2,this.browserRendererId=e,this.logger=t}return e.getOrCreate=function(t){return e.instance||(e.instance=new e(0,t)),this.instance},e.prototype.processBatch=function(e,t,n){return r(this,void 0,void 0,function(){var r;return o(this,function(o){switch(o.label){case 0:return e<this.nextBatchId?[4,this.completeBatch(n,e)]:[3,2];case 1:return o.sent(),this.logger.log(a.LogLevel.Debug,"Batch "+e+" already processed. Waiting for batch "+this.nextBatchId+"."),[2];case 2:return e>this.nextBatchId?this.fatalError?(this.logger.log(a.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(a.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(a.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new s.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(a.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(a.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(78),o=Math.pow(2,32),i=Math.pow(2,21)-1,s=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new a(e),this.editReader=new u(e,t),this.frameReader=new c(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=s;var a=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<<r,i<128)break;r+=7}return n}(this.batchDataUint8,n),i=n+((t=o)<128?1:t<16384?2:t<2097152?3:4),s=new Uint8Array(this.batchDataUint8.buffer,this.batchDataUint8.byteOffset+i,o);return r.decodeUtf8(s)},e}(),f=function(){function e(e){this.batchDataUint8=e}return e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}(),h=function(){function e(e){this.batchDataUint8=e}return e.prototype.offset=function(e){return 0},e.prototype.count=function(e){return p(this.batchDataUint8,e)},e.prototype.values=function(e){return e+4},e}();function p(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function d(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t<n;){var i=e[t++];if(0===i)break;if(0==(128&i))r.push(i);else if(192==(224&i)){var s=63&e[t++];r.push((31&i)<<6|s)}else if(224==(240&i)){var s=63&e[t++],a=63&e[t++];r.push((31&i)<<12|s<<6|a)}else if(240==(248&i)){var s=63&e[t++],a=63&e[t++],u=63&e[t++],c=(7&i)<<18|s<<12|a<<6|u;c>65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(15),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(10),s=n(11),a=function(){function e(e){this.circuitId=void 0,this.components=e}return e.prototype.reconnect=function(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.invoke("ConnectCircuit",this.circuitId)},e.prototype.initialize=function(e){if(this.circuitId)throw new Error("Circuit host '"+this.circuitId+"' already initialized.");this.circuitId=e},e.prototype.startCircuit=function(e){return r(this,void 0,void 0,function(){var t;return o(this,function(n){switch(n.label){case 0:return[4,e.invoke("StartCircuit",i.internalFunctions.getBaseURI(),i.internalFunctions.getLocationHref(),JSON.stringify(this.components.map(function(e){return e.toRecord()})))];case 1:return(t=n.sent())?(this.initialize(t),[2,!0]):[2,!1]}})})},e.prototype.resolveElement=function(e){var t=Number.parseInt(e);if(Number.isNaN(t))throw new Error("Invalid sequence number '"+e+"'.");return s.toLogicalRootCommentElement(this.components[t].start,this.components[t].end)},e}();t.CircuitDescriptor=a;var u=function(){function e(e,t,n,r,o){this.type=e,this.start=t,this.end=n,this.sequence=r,this.descriptor=o}return e.prototype.toRecord=function(){return{type:this.type,sequence:this.sequence,descriptor:this.descriptor}},e}();t.ComponentDescriptor=u,t.discoverComponents=function(e){for(var t=function e(t){if(!t.hasChildNodes())return[];for(var n=[],r=new h(t.childNodes);r.next()&&r.currentElement;){var o=l(r);if(o)n.push(o);else for(var i=e(r.currentElement),s=0;s<i.length;s++){var a=i[s];n.push(a)}}return n}(e),n=[],r=0;r<t.length;r++){var o=t[r],i=new u(o.type,o.start,o.end,o.sequence,o.descriptor);n.push(i)}return n.sort(function(e,t){return e.sequence-t.sequence})};var c=/\W*Blazor:[^{]*(.*)$/;function l(e){var t=e.currentElement;if(t&&t.nodeType===Node.COMMENT_NODE&&t.textContent){var n=new RegExp(c).exec(t.textContent),r=n&&n[1];if(!r)return;try{return function(e,t,n){var r=JSON.parse(e),o=r.type,i=r.sequence,s=r.descriptor,a=r.prerenderId;if("server"!==o)throw new Error("Invalid component type '"+o+"'.");if(!s)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===i)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(i))throw new Error("Error parsing the sequence '"+i+"' for component '"+e+"'");if(a){var u=function(e,t){for(;t.next()&&t.currentElement;){var n=t.currentElement;if(n.nodeType===Node.COMMENT_NODE&&n.textContent){var r=new RegExp(c).exec(n.textContent),o=r&&r[1];if(o)return f(o,e),n}}return}(a,n);if(!u)throw new Error("Could not find an end component comment for '"+t+"'");return{type:o,sequence:i,descriptor:s,start:t,prerenderId:a,end:u}}return{type:o,sequence:i,descriptor:s,start:t}}(r,t,e)}catch(e){throw new Error("Found malformed component comment at "+t.textContent)}}}function f(e,t){var n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error("Invalid end of component comment: '"+e+"'");var r=n.prerenderId;if(!r)throw new Error("End of component comment must have a value for the prerendered property: '"+e+"'");if(r!==t)throw new Error("End of component comment prerendered property must match the start comment prerender id: '"+t+"', '"+r+"'")}var h=function(){function e(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}return e.prototype.next=function(){return this.currentIndex++,this.currentIndex<this.length?(this.currentElement=this.childNodes[this.currentIndex],!0):(this.currentElement=void 0,!1)},e}()},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=n(15);t.resolveOptions=function(e){var t=r({},i,e);return e&&e.reconnectionOptions&&(t.reconnectionOptions=r({},i.reconnectionOptions,e.reconnectionOptions)),t};var i={configureSignalR:function(e){},logLevel:o.LogLevel.Warning,reconnectionOptions:{maxRetries:5,retryIntervalMilliseconds:3e3,dialogId:"components-reconnect-modal"}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(83),s=n(84),a=n(15),u=function(){function e(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||function(){return window.Blazor.reconnect()}}return e.prototype.onConnectionDown=function(e,t){if(!this._reconnectionDisplay){var n=document.getElementById(e.dialogId);this._reconnectionDisplay=n?new s.UserSpecifiedDisplay(n):new i.DefaultReconnectDisplay(e.dialogId,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new c(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))},e.prototype.onConnectionUp=function(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)},e}();t.DefaultReconnectionHandler=u;var c=function(){function e(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}return e.prototype.dispose=function(){this.isDisposed=!0,this.reconnectDisplay.hide()},e.prototype.attemptPeriodicReconnection=function(e){return r(this,void 0,void 0,function(){var t,n;return o(this,function(r){switch(r.label){case 0:t=0,r.label=1;case 1:return t<e.maxRetries?[4,this.delay(e.retryIntervalMilliseconds)]:[3,7];case 2:if(r.sent(),this.isDisposed)return[3,7];r.label=3;case 3:return r.trys.push([3,5,,6]),[4,this.reconnectCallback()];case 4:return r.sent()?[2]:(this.reconnectDisplay.rejected(),[2]);case 5:return n=r.sent(),this.logger.log(a.LogLevel.Error,n),[3,6];case 6:return t++,[3,1];case 7:return this.reconnectDisplay.failed(),[2]}})})},e.prototype.delay=function(e){return new Promise(function(t){return setTimeout(t,e)})},e}()},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0});var i=n(15),s=function(){function e(e,t,n){var s=this;this.document=t,this.logger=n,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry</button><p>Alternatively, <a href>reload</a></p>',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.button.addEventListener("click",function(){return r(s,void 0,void 0,function(){var e;return o(this,function(t){switch(t.label){case 0:this.show(),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,window.Blazor.reconnect()];case 2:return t.sent()||this.rejected(),[3,4];case 3:return e=t.sent(),this.logger.log(i.LogLevel.Error,e),this.failed(),[3,4];case 4:return[2]}})})}),this.reloadParagraph.querySelector("a").addEventListener("click",function(){return location.reload()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.message.innerHTML="Reconnection failed. Try <a href>reloading</a> the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=s},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(20),o=n(9),i=n(2),s=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o<e.byteLength;){var i=0,s=0,a=void 0;do{s|=(127&(a=n[o+i]))<<r[i],i++}while(i<Math.min(5,e.byteLength-o)&&0!=(128&a));if(0!=(128&a)&&i<5)throw new Error("Cannot read message size.");if(5===i&&a>7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+s))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+s):n.subarray(o+i,o+i+s)),o=o+i+s}return t},e}();var a=new Uint8Array([145,i.MessageType.Ping]),u=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],a=0,u=s.parse(e);a<u.length;a++){var c=u[a],l=this.parseMessage(c,t);l&&o.push(l)}return o},e.prototype.writeMessage=function(e){switch(e.type){case i.MessageType.Invocation:return this.writeInvocation(e);case i.MessageType.StreamInvocation:return this.writeStreamInvocation(e);case i.MessageType.StreamItem:return this.writeStreamItem(e);case i.MessageType.Completion:return this.writeCompletion(e);case i.MessageType.Ping:return s.write(a);case i.MessageType.CancelInvocation:return this.writeCancelInvocation(e);default:throw new Error("Invalid message type.")}},e.prototype.parseMessage=function(e,t){if(0===e.length)throw new Error("Invalid payload.");var n=o().decode(r.Buffer.from(e));if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");var s=n[0];switch(s){case i.MessageType.Invocation:return this.createInvocationMessage(this.readHeaders(n),n);case i.MessageType.StreamItem:return this.createStreamItemMessage(this.readHeaders(n),n);case i.MessageType.Completion:return this.createCompletionMessage(this.readHeaders(n),n);case i.MessageType.Ping:return this.createPingMessage(n);case i.MessageType.Close:return this.createCloseMessage(n);default:return t.log(i.LogLevel.Information,"Unknown message type '"+s+"' ignored."),null}},e.prototype.createCloseMessage=function(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return s.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return s.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return s.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return s.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return s.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return c}),n.d(t,"MessagePackHubProtocol",function(){return u});var c="3.1.1-dev"}]); \ No newline at end of file diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js index 9f9d6b369d76..88dbb56b2f41 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webassembly.js +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -1 +1 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function u(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=u,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");u(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),u=r.values(o),l=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f<l;f++){var p=t.updatedComponentsEntry(u,f),m=d.componentId(p),h=d.edits(p);n.updateComponent(t,m,h,c)}var v=t.disposedComponentIds(),y=r.values(v),g=r.count(v);for(f=0;f<g;f++)m=t.disposedComponentIdsEntry(y,f),n.disposeComponent(m);var b=t.disposedEventHandlerIds(),w=r.values(b),E=r.count(b);for(f=0;f<E;f++){var _=t.disposedEventHandlerIdsEntry(w,f);n.disposeEventHandler(_)}i&&(i=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){i=!0}},,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17);var a,i=n(5),u=!1,l=!1,s=null;function c(e,t){var n=p(e);if(!t&&m(n))d(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function d(e,t){i.resetScrollAfterNextBatch(),history.pushState(null,"",e),f(t)}function f(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return s?[4,s(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(a=a||document.createElement("a")).href=e,a.href}function m(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(s=e,l)return;l=!0,window.addEventListener("popstate",function(){return f(!1)})},enableNavigationInterception:function(){u=!0},navigateTo:c,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(u&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));m(r)&&(e.preventDefault(),d(r,!0))}}})},t.navigateTo=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),a=p("_blazorLogicalEnd");function i(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function u(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(l(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n<i.length){var u=i[n];u.parentNode.insertBefore(e,u),i.splice(n,0,a)}else f(e,t),i.push(a);a[o]=t,r in a||(a[r]=[])}function l(e){return e[o]||null}function s(e){return e[r]}function c(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function d(e){var t=s(l(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function f(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=d(t);n?n.parentNode.insertBefore(e,n):f(e,l(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=i(n,!0),u=s(r);return Array.from(n.childNodes).forEach(function(e){return u.push(e)}),e[o]=r,t&&(e[a]=t,i(t,!0)),i(e,!0)},t.toLogicalElement=i,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return u(n,e,t),n},t.insertLogicalChild=u,t.removeLogicalChild=function e(t,n){var r=s(t).splice(n,1)[0];if(r instanceof Comment)for(var o=s(r);o.length>0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=l,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=l(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function u(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function l(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,u=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var l=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,l)}catch(e){c(i,!1,e)}return u}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return u(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return l(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,d(t));return null==n?null:JSON.stringify(n,h)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,d(n)))});e&&r.then(function(t){return s().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],h))},function(t){return s().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,f(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);c(parseInt(e),t,r)}};var m=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return u(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return l(null,e,this._id,t)},e.prototype.dispose=function(){l(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function h(e,t){return t instanceof m?t.serializeAsArg():t}i(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new m(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(12),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),a=n(13),i=n(31),u=n(19),l=n(12),s=document.createElement("template"),c=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},f={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var a={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};u.dispatchEvent(a,r.data)}(e,t.browserRendererId,n,r,o)}),l.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),f[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var i=f[t];if(i){var u=a.getLogicalSiblingEnd(i);delete f[t],u?function(e,t){var n=a.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=a.getLogicalChildrenArray(n),o=r.indexOf(e)+1,i=r.indexOf(t),u=o;u<=i;u++)a.removeLogicalChild(n,o);e.textContent="!"}(i,u):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(i)}var l=a.getClosestDomElement(o).ownerDocument,s=l&&l.activeElement;this.applyEdits(e,t,o,0,n,r),s instanceof HTMLElement&&l&&l.activeElement!==s&&s.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,i,u){for(var l,s=0,c=o,d=e.arrayBuilderSegmentReader,f=e.editReader,p=e.frameReader,m=d.values(i),h=d.offset(i),v=h+d.count(i),y=h;y<v;y++){var g=e.diffReader.editsEntry(m,y),b=f.editType(g);switch(b){case r.EditType.prependFrame:var w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);this.insertFrame(e,t,n,c+_,u,E,w);break;case r.EditType.removeFrame:_=f.siblingIndex(g);a.removeLogicalChild(n,c+_);break;case r.EditType.setAttribute:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,I,E);break;case r.EditType.removeAttribute:var I;_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var C=f.removedAttributeName(g);this.tryApplySpecialProperty(e,I,C,null)||I.removeAttribute(C);break;case r.EditType.updateText:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);var S=a.getLogicalChild(n,c+_);if(!(S instanceof Text))throw new Error("Cannot set text content on non-text child");S.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=f.newTreeIndex(g),E=e.referenceFramesEntry(u,w),_=f.siblingIndex(g);a.removeLogicalChild(n,c+_),this.insertMarkup(e,n,c+_,E);break;case r.EditType.stepIn:_=f.siblingIndex(g);n=a.getLogicalChild(n,c+_),s++,c=0;break;case r.EditType.stepOut:n=a.getLogicalParent(n),c=0===--s?o:0;break;case r.EditType.permutationListEntry:(l=l||[]).push({fromSiblingIndex:c+f.siblingIndex(g),toSiblingIndex:c+f.moveToSiblingIndex(g)});break;case r.EditType.permutationListEnd:a.permuteLogicalChildren(n,l),l=void 0;break;default:throw new Error("Unknown edit type: "+b)}}},e.prototype.insertFrame=function(e,t,n,o,a,u,l){var s=e.frameReader,c=s.frameType(u);switch(c){case r.FrameType.element:return this.insertElement(e,t,n,o,a,u,l),1;case r.FrameType.text:return this.insertText(e,n,o,u),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,u),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,a,l+1,l+s.subtreeLength(u));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return i.applyCaptureIdToElement(n,s.elementReferenceCaptureId(u)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,u),1;default:throw new Error("Unknown frame type: "+c)}},e.prototype.insertElement=function(e,t,n,o,i,u,l){var s=e.frameReader,c=s.elementName(u),d="svg"===c||a.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",c):document.createElement(c),f=a.toLogicalElement(d);a.insertLogicalChild(d,n,o);for(var p=l+s.subtreeLength(u),m=l+1;m<p;m++){var h=e.referenceFramesEntry(i,m);if(s.frameType(h)!==r.FrameType.attribute){this.insertFrameRange(e,t,f,0,i,m,p);break}this.applyAttribute(e,t,d,h)}if(d instanceof HTMLSelectElement&&"_blazorSelectValue"in d){var v=d._blazorSelectValue;d.value=v,delete d._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=a.createAndInsertLogicalContainer(t,n),i=e.frameReader.componentId(r);this.attachComponentToElement(i,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),i=document.createTextNode(o);a.insertLogicalChild(i,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,i=a.createAndInsertLogicalContainer(t,n),u=e.frameReader.markupContent(r),l=(o=u,a.isSvgElement(t)?(c.innerHTML=o||" ",c):(s.innerHTML=o||" ",s.content)),d=0;l.firstChild;)a.insertLogicalChild(l.firstChild,i,d++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,a=o.attributeName(r),i=o.attributeEventHandlerId(r);if(i){var u=h(a);this.eventDelegator.setListener(n,u,i,t)}else this.tryApplySpecialProperty(e,n,a,r)||n.setAttribute(a,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var a=h(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,a,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");a=h(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,a,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var a=n?r.attributeValue(n):null;return t.value=a,"SELECT"===t.tagName&&(t._blazorSelectValue=a),!0;case"OPTION":(a=n?r.attributeValue(n):null)?t.setAttribute("value",a):t.removeAttribute("value");var i=this.findClosestAncestorSelectElement(t);return i&&"_blazorSelectValue"in i&&i._blazorSelectValue===a&&(this.tryApplyValueProperty(e,i,n),delete i._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,a,i){for(var u=r,l=a;l<i;l++){var s=e.referenceFramesEntry(o,l);r+=this.insertFrame(e,t,n,r,o,s,l),l+=m(e,s)}return r-u},e}();function m(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function h(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),a=c(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),i=c(["click","dblclick","mousedown","mousemove","mouseup"]),u=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new l(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{var i={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(i),o.setHandler(t,i)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,u=e.target,l=null,s=a.hasOwnProperty(e.type),c=!1;u;){var d=this.getEventHandlerInfosForElement(u,!1);if(d){var f=d.getHandler(e.type);if(f&&(t=u,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&i.hasOwnProperty(n)&&t.disabled))){l||(l=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(f.renderingComponentId,e);this.onEvent(e,f.eventHandlerId,l,p)}d.stopPropagation(e.type)&&(c=!0),d.preventDefault(e.type)&&e.preventDefault()}u=s||c?null:u.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new s:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=u;var l=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=a.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),s=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function c(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==i.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var u=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:u});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},a(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",a(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},a(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},a(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function a(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var i=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0});var a=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),a||(a=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,function(e,t,n){"use strict";function r(e){var t=e.substring(e.lastIndexOf("/")+1),n=t.indexOf("?");return n<0?t:t.substring(0,n)}Object.defineProperty(t,"__esModule",{value:!0}),t.getFileNameFromUrl=r,t.getAssemblyNameFromUrl=function(e){return r(e).replace(/\.dll$/,"")}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{l(r.next(e))}catch(e){a(e)}}function u(e){try{l(r.throw(e))}catch(e){a(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,u)}l((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(17),n(24);var a=n(18),i=n(46),u=n(5),l=n(48),s=n(33),c=n(19),d=!1;function f(e){return r(this,void 0,void 0,function(){var e,t,n,s,f=this;return o(this,function(m){switch(m.label){case 0:if(d)throw new Error("Blazor has already started.");return d=!0,c.setEventDispatcher(function(e,t){return DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","DispatchEvent",e,JSON.stringify(t))}),e=a.setPlatform(i.monoPlatform),window.Blazor.platform=e,window.Blazor._internal.renderBatch=function(e,t){u.renderBatch(e,new l.SharedMemoryRenderBatch(t))},window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return r(f,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}})})}),[4,p()];case 1:(t=m.sent()).linkerEnabled||console.info("Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414"),n=t.assemblies.map(function(e){return"_framework/_bin/"+e}),m.label=2;case 2:return m.trys.push([2,4,,5]),[4,e.start(n)];case 3:return m.sent(),[3,5];case 4:throw s=m.sent(),new Error("Failed to start platform. Reason: "+s);case 5:return e.callEntryPoint(t.entryAssembly),[2]}})})}function p(){return r(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,fetch("_framework/blazor.boot.json",{method:"Get",credentials:"include"})];case 1:return[2,e.sent().json()]}})})}window.Blazor.start=f,s.shouldAutoStart()&&f().catch(function(e){Module.printErr(e)})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o=n(35),a=n(47),i=n(32),u="appBinDir",l=Math.pow(2,32),s=Math.pow(2,21)-1;t.monoPlatform={start:function(e){return new Promise(function(t,n){var l,s;a.attachDebuggerHotkey(e),window.Browser={init:function(){}},l=function(){window.Module=function(e,t,n){var l={},s=["DEBUGGING ENABLED"];return l.print=function(e){return s.indexOf(e)<0&&console.log("WASM: "+e)},l.printErr=function(e){console.error("WASM: "+e),i.showErrorNotification()},l.preRun=[],l.postRun=[],l.preloadPlugins=[],l.locateFile=function(e){switch(e){case"mono.wasm":return"_framework/wasm/mono.wasm";default:return e}},l.preRun.push(function(){var t=Module.cwrap("mono_wasm_add_assembly",null,["string","number","number"]);r=Module.cwrap("mono_wasm_string_get_utf8","number",["number"]),MONO.loaded_files=[],e.forEach(function(e){var r=o.getFileNameFromUrl(e),a="blazor:"+r;addRunDependency(a),function(e){return new Promise(function(t,n){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){if(200==r.status||0==r.status&&r.response){var e=new Uint8Array(r.response);t(e)}else n(r)},r.onerror=n,r.send(void 0)})}(e).then(function(n){var o,i=Module._malloc(n.length);new Uint8Array(Module.HEAPU8.buffer,i,n.length).set(n),t(r,i,n.length),MONO.loaded_files.push((o=e,c.href=o,c.href)),removeRunDependency(a)},function(e){e instanceof XMLHttpRequest&&404===e.status&&r.match(/\.pdb$/)||n(e),removeRunDependency(a)})})}),l.postRun.push(function(){var e,n,r;MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE","true"),Module.cwrap("mono_wasm_load_runtime",null,["string","number"])(u,a.hasDebuggingEnabled()?1:0),MONO.mono_wasm_runtime_is_ready=!0,e=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","InvokeDotNet"),n=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","BeginInvokeDotNet"),r=f("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop.MonoWebAssemblyJSRuntime","EndInvokeJS"),DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,t,r,o,a){if(!o&&!t)throw new Error("Either assemblyName or dotNetObjectId must have a non null value.");var i=o?o.toString():t;n(e?e.toString():null,i,r,a)},endInvokeJSFromDotNet:function(e,t,n){r(n)},invokeDotNetFromJS:function(t,n,r,o){return e(t||null,n,r?r.toString():null,o)}}),t()}),l}(e,t,n),function(){if("undefined"==typeof WebAssembly||!WebAssembly.validate)throw new Error("This browser does not support WebAssembly.");var e=document.createElement("script");e.src="_framework/wasm/mono.js",e.defer=!0,document.body.appendChild(e)}()},s=document.createElement("script"),window.__wasmmodulecallback__=l,s.type="text/javascript",s.text="var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;",document.body.appendChild(s)})},callEntryPoint:function(e){f("Microsoft.AspNetCore.Blazor","Microsoft.AspNetCore.Blazor.Hosting.EntrypointInvoker","InvokeEntrypoint")(e,null)},toJavaScriptString:function(e){var t=r(e),n=Module.UTF8ToString(t);return Module._free(t),n},toUint8Array:function(e){var t=d(e),n=Module.getValue(t,"i32");return new Uint8Array(Module.HEAPU8.buffer,t+4,n)},getArrayLength:function(e){return Module.getValue(d(e),"i32")},getArrayEntryPtr:function(e,t,n){return d(e)+4+t*n},getObjectFieldsBaseAddress:function(e){return e+8},readInt16Field:function(e,t){return Module.getValue(e+(t||0),"i16")},readInt32Field:function(e,t){return Module.getValue(e+(t||0),"i32")},readUint64Field:function(e,t){var n=e+(t||0)>>2,r=Module.HEAPU32[n+1];if(r>s)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*l+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var c=document.createElement("a");function d(e){return e+12}function f(e,t,n){var r="["+e+"] "+t+":"+n;return Module.mono_bind_static_method(r)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=u,this.editReader=l,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,u.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},u={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,l.structLength)}},l={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=47)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(17);var r=n(26),o=n(11),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f<u;f++){var p=t.updatedComponentsEntry(l,f),m=d.componentId(p),h=d.edits(p);n.updateComponent(t,m,h,c)}var v=t.disposedComponentIds(),y=r.values(v),g=r.count(v);for(f=0;f<g;f++)m=t.disposedComponentIdsEntry(y,f),n.disposeComponent(m);var b=t.disposedEventHandlerIds(),w=r.values(b),E=r.count(b);for(f=0;f<E;f++){var _=t.disposedEventHandlerIdsEntry(w,f);n.disposeEventHandler(_)}i&&(i=!1,window.scrollTo&&window.scrollTo(0,0))},t.resetScrollAfterNextBatch=function(){i=!0}},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(16);var a,i=n(5),l=!1,u=!1,s=null;function c(e,t){var n=p(e);if(!t&&m(n))d(n,!1);else if(t&&location.href===e){var r=e+"?";history.replaceState(null,"",r),location.replace(e)}else location.href=e}function d(e,t){i.resetScrollAfterNextBatch(),history.pushState(null,"",e),f(t)}function f(e){return r(this,void 0,void 0,function(){return o(this,function(t){switch(t.label){case 0:return s?[4,s(location.href,e)]:[3,2];case 1:t.sent(),t.label=2;case 2:return[2]}})})}function p(e){return(a=a||document.createElement("a")).href=e,a.href}function m(e){var t,n=(t=document.baseURI).substr(0,t.lastIndexOf("/")+1);return e.startsWith(n)}t.internalFunctions={listenForNavigationEvents:function(e){if(s=e,u)return;u=!0,window.addEventListener("popstate",function(){return f(!1)})},enableNavigationInterception:function(){l=!0},navigateTo:c,getBaseURI:function(){return document.baseURI},getLocationHref:function(){return location.href}},t.attachToEventDelegator=function(e){e.notifyAfterClick(function(e){if(l&&0===e.button&&!function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e)&&!e.defaultPrevented){var t=function e(t,n){return t?t.tagName===n?t:e(t.parentElement,n):null}(e.target,"A");if(t&&t.hasAttribute("href")){var n=t.getAttribute("target");if(n&&"_self"!==n)return;var r=p(t.getAttribute("href"));m(r)&&(e.preventDefault(),d(r,!0))}}})},t.navigateTo=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=p("_blazorLogicalChildren"),o=p("_blazorLogicalParent"),a=p("_blazorLogicalEnd");function i(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n<i.length){var l=i[n];l.parentNode.insertBefore(e,l),i.splice(n,0,a)}else f(e,t),i.push(a);a[o]=t,r in a||(a[r]=[])}function u(e){return e[o]||null}function s(e){return e[r]}function c(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function d(e){var t=s(u(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function f(e,t){if(t instanceof Element)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error("Cannot append node because the parent is not a valid logical element. Parent: "+t);var n=d(t);n?n.parentNode.insertBefore(e,n):f(e,u(t))}}function p(e){return"function"==typeof Symbol?Symbol():e}t.toLogicalRootCommentElement=function(e,t){if(!e.parentNode)throw new Error("Comment not connected to the DOM "+e.textContent);var n=e.parentNode,r=i(n,!0),l=s(r);return Array.from(n.childNodes).forEach(function(e){return l.push(e)}),e[o]=r,t&&(e[a]=t,i(t,!0)),i(e,!0)},t.toLogicalElement=i,t.createAndInsertLogicalContainer=function(e,t){var n=document.createComment("!");return l(n,e,t),n},t.insertLogicalChild=l,t.removeLogicalChild=function e(t,n){var r=s(t).splice(n,1)[0];if(r instanceof Comment)for(var o=s(r);o.length>0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return l(e,t,null,n)},e.invokeMethodAsync=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return u(e,t,null,n)},e.jsCallDispatcher={findJSFunction:p,invokeJSFromDotNet:function(e,t){var n=p(e).apply(null,d(t));return null==n?null:JSON.stringify(n,h)},beginInvokeJSFromDotNet:function(e,t,n){var r=new Promise(function(e){e(p(t).apply(null,d(n)))});e&&r.then(function(t){return s().endInvokeJSFromDotNet(e,!0,JSON.stringify([e,!0,t],h))},function(t){return s().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,f(t)]))})},endInvokeDotNetFromJS:function(e,t,n){var r=t?n:new Error(n);c(parseInt(e),t,r)}};var m=function(){function e(e){this._id=e}return e.prototype.invokeMethod=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return l(null,e,this._id,t)},e.prototype.invokeMethodAsync=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return u(null,e,this._id,t)},e.prototype.dispose=function(){u(null,"__Dispose",this._id,null).catch(function(e){return console.error(e)})},e.prototype.serializeAsArg=function(){return{__dotNetObject:this._id}},e}();function h(e,t){return t instanceof m?t.serializeAsArg():t}i(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__dotNetObject")?new m(t.__dotNetObject):t})}(r||(r={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(10),o=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),o=n(28),a=n(11),i=n(31),l=n(18),u=n(10),s=document.createElement("template"),c=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},f={},p=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator(function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var a={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};l.dispatchEvent(a,r.data)}(e,t.browserRendererId,n,r,o)}),u.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),f[e]=t},e.prototype.updateComponent=function(e,t,n,r){var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var i=f[t];if(i){var l=a.getLogicalSiblingEnd(i);delete f[t],l?function(e,t){var n=a.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=a.getLogicalChildrenArray(n),o=r.indexOf(e)+1,i=r.indexOf(t),l=o;l<=i;l++)a.removeLogicalChild(n,o);e.textContent="!"}(i,l):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(i)}var u=a.getClosestDomElement(o).ownerDocument,s=u&&u.activeElement;this.applyEdits(e,t,o,0,n,r),s instanceof HTMLElement&&u&&u.activeElement!==s&&s.focus()},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,i,l){for(var u,s=0,c=o,d=e.arrayBuilderSegmentReader,f=e.editReader,p=e.frameReader,m=d.values(i),h=d.offset(i),v=h+d.count(i),y=h;y<v;y++){var g=e.diffReader.editsEntry(m,y),b=f.editType(g);switch(b){case r.EditType.prependFrame:var w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);this.insertFrame(e,t,n,c+_,l,E,w);break;case r.EditType.removeFrame:_=f.siblingIndex(g);a.removeLogicalChild(n,c+_);break;case r.EditType.setAttribute:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof Element))throw new Error("Cannot set attribute on non-element child");this.applyAttribute(e,t,I,E);break;case r.EditType.removeAttribute:var I;_=f.siblingIndex(g);if(!((I=a.getLogicalChild(n,c+_))instanceof HTMLElement))throw new Error("Cannot remove attribute from non-element child");var S=f.removedAttributeName(g);this.tryApplySpecialProperty(e,I,S,null)||I.removeAttribute(S);break;case r.EditType.updateText:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);var C=a.getLogicalChild(n,c+_);if(!(C instanceof Text))throw new Error("Cannot set text content on non-text child");C.textContent=p.textContent(E);break;case r.EditType.updateMarkup:w=f.newTreeIndex(g),E=e.referenceFramesEntry(l,w),_=f.siblingIndex(g);a.removeLogicalChild(n,c+_),this.insertMarkup(e,n,c+_,E);break;case r.EditType.stepIn:_=f.siblingIndex(g);n=a.getLogicalChild(n,c+_),s++,c=0;break;case r.EditType.stepOut:n=a.getLogicalParent(n),c=0===--s?o:0;break;case r.EditType.permutationListEntry:(u=u||[]).push({fromSiblingIndex:c+f.siblingIndex(g),toSiblingIndex:c+f.moveToSiblingIndex(g)});break;case r.EditType.permutationListEnd:a.permuteLogicalChildren(n,u),u=void 0;break;default:throw new Error("Unknown edit type: "+b)}}},e.prototype.insertFrame=function(e,t,n,o,a,l,u){var s=e.frameReader,c=s.frameType(l);switch(c){case r.FrameType.element:return this.insertElement(e,t,n,o,a,l,u),1;case r.FrameType.text:return this.insertText(e,n,o,l),1;case r.FrameType.attribute:throw new Error("Attribute frames should only be present as leading children of element frames.");case r.FrameType.component:return this.insertComponent(e,n,o,l),1;case r.FrameType.region:return this.insertFrameRange(e,t,n,o,a,u+1,u+s.subtreeLength(l));case r.FrameType.elementReferenceCapture:if(n instanceof Element)return i.applyCaptureIdToElement(n,s.elementReferenceCaptureId(l)),0;throw new Error("Reference capture frames can only be children of element frames.");case r.FrameType.markup:return this.insertMarkup(e,n,o,l),1;default:throw new Error("Unknown frame type: "+c)}},e.prototype.insertElement=function(e,t,n,o,i,l,u){var s=e.frameReader,c=s.elementName(l),d="svg"===c||a.isSvgElement(n)?document.createElementNS("http://www.w3.org/2000/svg",c):document.createElement(c),f=a.toLogicalElement(d);a.insertLogicalChild(d,n,o);for(var p=u+s.subtreeLength(l),m=u+1;m<p;m++){var h=e.referenceFramesEntry(i,m);if(s.frameType(h)!==r.FrameType.attribute){this.insertFrameRange(e,t,f,0,i,m,p);break}this.applyAttribute(e,t,d,h)}if(d instanceof HTMLSelectElement&&"_blazorSelectValue"in d){var v=d._blazorSelectValue;d.value=v,delete d._blazorSelectValue}},e.prototype.insertComponent=function(e,t,n,r){var o=a.createAndInsertLogicalContainer(t,n),i=e.frameReader.componentId(r);this.attachComponentToElement(i,o)},e.prototype.insertText=function(e,t,n,r){var o=e.frameReader.textContent(r),i=document.createTextNode(o);a.insertLogicalChild(i,t,n)},e.prototype.insertMarkup=function(e,t,n,r){for(var o,i=a.createAndInsertLogicalContainer(t,n),l=e.frameReader.markupContent(r),u=(o=l,a.isSvgElement(t)?(c.innerHTML=o||" ",c):(s.innerHTML=o||" ",s.content)),d=0;u.firstChild;)a.insertLogicalChild(u.firstChild,i,d++)},e.prototype.applyAttribute=function(e,t,n,r){var o=e.frameReader,a=o.attributeName(r),i=o.attributeEventHandlerId(r);if(i){var l=h(a);this.eventDelegator.setListener(n,l,i,t)}else this.tryApplySpecialProperty(e,n,a,r)||n.setAttribute(a,o.attributeValue(r))},e.prototype.tryApplySpecialProperty=function(e,t,n,r){switch(n){case"value":return this.tryApplyValueProperty(e,t,r);case"checked":return this.tryApplyCheckedProperty(e,t,r);default:return!!n.startsWith("__internal_")&&(this.applyInternalAttribute(e,t,n.substring("__internal_".length),r),!0)}},e.prototype.applyInternalAttribute=function(e,t,n,r){var o=r?e.frameReader.attributeValue(r):null;if(n.startsWith("stopPropagation_")){var a=h(n.substring("stopPropagation_".length));this.eventDelegator.setStopPropagation(t,a,null!==o)}else{if(!n.startsWith("preventDefault_"))throw new Error("Unsupported internal attribute '"+n+"'");a=h(n.substring("preventDefault_".length));this.eventDelegator.setPreventDefault(t,a,null!==o)}},e.prototype.tryApplyValueProperty=function(e,t,n){var r=e.frameReader;if("INPUT"===t.tagName&&"time"===t.getAttribute("type")&&!t.getAttribute("step")){var o=n?r.attributeValue(n):null;if(o)return t.value=o.substring(0,5),!0}switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":var a=n?r.attributeValue(n):null;return t.value=a,"SELECT"===t.tagName&&(t._blazorSelectValue=a),!0;case"OPTION":(a=n?r.attributeValue(n):null)?t.setAttribute("value",a):t.removeAttribute("value");var i=this.findClosestAncestorSelectElement(t);return i&&"_blazorSelectValue"in i&&i._blazorSelectValue===a&&(this.tryApplyValueProperty(e,i,n),delete i._blazorSelectValue),!0;default:return!1}},e.prototype.tryApplyCheckedProperty=function(e,t,n){if("INPUT"===t.tagName){var r=n?e.frameReader.attributeValue(n):null;return t.checked=null!==r,!0}return!1},e.prototype.findClosestAncestorSelectElement=function(e){for(;e;){if(e instanceof HTMLSelectElement)return e;e=e.parentElement}return null},e.prototype.insertFrameRange=function(e,t,n,r,o,a,i){for(var l=r,u=a;u<i;u++){var s=e.referenceFramesEntry(o,u);r+=this.insertFrame(e,t,n,r,o,s,u),u+=m(e,s)}return r-l},e}();function m(e,t){var n=e.frameReader;switch(n.frameType(t)){case r.FrameType.component:case r.FrameType.element:case r.FrameType.region:return n.subtreeLength(t)-1;default:return 0}}function h(e){if(e.startsWith("on"))return e.substring(2);throw new Error("Attribute should be an event name, but doesn't start with 'on'. Value: '"+e+"'")}t.BrowserRenderer=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t.EditType||(t.EditType={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(t.FrameType||(t.FrameType={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(29),o=n(30),a=c(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),i=c(["click","dblclick","mousedown","mousemove","mouseup"]),l=function(){function e(t){this.onEvent=t,this.afterClickCallbacks=[];var n=++e.nextEventDelegatorId;this.eventsCollectionKey="_blazorEvents_"+n,this.eventInfoStore=new u(this.onGlobalEvent.bind(this))}return e.prototype.setListener=function(e,t,n,r){var o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{var i={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(i),o.setHandler(t,i)}},e.prototype.removeListener=function(e){var t=this.eventInfoStore.remove(e);if(t){var n=t.element,r=this.getEventHandlerInfosForElement(n,!1);r&&r.removeHandler(t.eventName)}},e.prototype.notifyAfterClick=function(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")},e.prototype.setStopPropagation=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)},e.prototype.setPreventDefault=function(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)},e.prototype.onGlobalEvent=function(e){if(e.target instanceof Element){for(var t,n,l=e.target,u=null,s=a.hasOwnProperty(e.type),c=!1;l;){var d=this.getEventHandlerInfosForElement(l,!1);if(d){var f=d.getHandler(e.type);if(f&&(t=l,n=e.type,!((t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&i.hasOwnProperty(n)&&t.disabled))){u||(u=r.EventForDotNet.fromDOMEvent(e));var p=o.EventFieldInfo.fromEvent(f.renderingComponentId,e);this.onEvent(e,f.eventHandlerId,u,p)}d.stopPropagation(e.type)&&(c=!0),d.preventDefault(e.type)&&e.preventDefault()}l=s||c?null:l.parentElement}"click"===e.type&&this.afterClickCallbacks.forEach(function(t){return t(e)})}},e.prototype.getEventHandlerInfosForElement=function(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new s:null},e.nextEventDelegatorId=0,e}();t.EventDelegator=l;var u=function(){function e(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={}}return e.prototype.add=function(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error("Event "+e.eventHandlerId+" is already tracked");this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)},e.prototype.addGlobalListener=function(e){if(this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;var t=a.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}},e.prototype.update=function(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error("Event "+t+" is already tracked");var n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n},e.prototype.remove=function(e){var t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];var n=t.eventName;0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t},e}(),s=function(){function e(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}return e.prototype.getHandler=function(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null},e.prototype.setHandler=function(e,t){this.handlers[e]=t},e.prototype.removeHandler=function(e){delete this.handlers[e]},e.prototype.preventDefault=function(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]},e.prototype.stopPropagation=function(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]},e}();function c(e){var t={};return e.forEach(function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){this.type=e,this.data=t}return e.fromDOMEvent=function(t){var n=t.target;switch(t.type){case"input":case"change":if(function(e){return-1!==i.indexOf(e.getAttribute("type"))}(n)){var o=function(e){var t=e.value,n=e.type;switch(n){case"date":case"datetime-local":case"month":return t;case"time":return 5===t.length?t+":00":t;case"week":return t}throw new Error("Invalid element type '"+n+"'.")}(n);return new e("change",{type:t.type,value:o})}var l=function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(n)?!!n.checked:n.value;return new e("change",{type:t.type,value:l});case"copy":case"cut":case"paste":return new e("clipboard",{type:t.type});case"drag":case"dragend":case"dragenter":case"dragleave":case"dragover":case"dragstart":case"drop":return new e("drag",function(e){return r({},a(e),{dataTransfer:e.dataTransfer})}(t));case"focus":case"blur":case"focusin":case"focusout":return new e("focus",{type:t.type});case"keydown":case"keyup":case"keypress":return new e("keyboard",function(e){return{type:e.type,key:e.key,code:e.code,location:e.location,repeat:e.repeat,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"contextmenu":case"click":case"mouseover":case"mouseout":case"mousemove":case"mousedown":case"mouseup":case"dblclick":return new e("mouse",a(t));case"error":return new e("error",function(e){return{type:e.type,message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno}}(t));case"loadstart":case"timeout":case"abort":case"load":case"loadend":case"progress":return new e("progress",function(e){return{type:e.type,lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total}}(t));case"touchcancel":case"touchend":case"touchmove":case"touchenter":case"touchleave":case"touchstart":return new e("touch",function(e){function t(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];t.push({identifier:r.identifier,clientX:r.clientX,clientY:r.clientY,screenX:r.screenX,screenY:r.screenY,pageX:r.pageX,pageY:r.pageY})}return t}return{type:e.type,detail:e.detail,touches:t(e.touches),targetTouches:t(e.targetTouches),changedTouches:t(e.changedTouches),ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}(t));case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointerenter":case"pointerleave":case"pointermove":case"pointerout":case"pointerover":case"pointerup":return new e("pointer",function(e){return r({},a(e),{pointerId:e.pointerId,width:e.width,height:e.height,pressure:e.pressure,tiltX:e.tiltX,tiltY:e.tiltY,pointerType:e.pointerType,isPrimary:e.isPrimary})}(t));case"wheel":case"mousewheel":return new e("wheel",function(e){return r({},a(e),{deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode})}(t));default:return new e("unknown",{type:t.type})}},e}();function a(e){return{type:e.type,detail:e.detail,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,button:e.button,buttons:e.buttons,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey}}t.EventForDotNet=o;var i=["date","datetime-local","month","time","week"]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){this.componentId=e,this.fieldValue=t}return e.fromEvent=function(t,n){var r=n.target;if(r instanceof Element){var o=function(e){if(e instanceof HTMLInputElement)return e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value};if(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)return{value:e.value};return null}(r);if(o)return new e(t,o.value)}return null},e}();t.EventFieldInfo=r},function(e,t,n){"use strict";function r(e){return"_bl_"+e}Object.defineProperty(t,"__esModule",{value:!0}),t.applyCaptureIdToElement=function(e,t){e.setAttribute(r(t),"")};DotNet.attachReviver(function(e,t){return t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?(n=t.__internalId,o="["+r(n)+"]",document.querySelector(o)):t;var n,o})},function(e,t,n){"use strict";function r(e){var t=e.substring(e.lastIndexOf("/")+1),n=t.indexOf("?");return n<0?t:t.substring(0,n)}Object.defineProperty(t,"__esModule",{value:!0}),t.getFileNameFromUrl=r,t.getAssemblyNameFromUrl=function(e){return r(e).replace(/\.dll$/,"")}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0});var a=!1;t.showErrorNotification=function(){return r(this,void 0,void 0,function(){var e;return o(this,function(t){return(e=document.querySelector("#blazor-error-ui"))&&(e.style.display="block"),a||(a=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach(function(e){e.onclick=function(e){location.reload(),e.preventDefault()}}),document.querySelectorAll("#blazor-error-ui .dismiss").forEach(function(e){e.onclick=function(e){var t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})),[2]})})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,,,,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,a){function i(e){try{u(r.next(e))}catch(e){a(e)}}function l(e){try{u(r.throw(e))}catch(e){a(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(i,l)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,r=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,l])}}};Object.defineProperty(t,"__esModule",{value:!0}),n(16),n(24);var a=n(17),i=n(48),l=n(32),u=n(5),s=n(50),c=n(34),d=n(18),f=!1;function p(e){return r(this,void 0,void 0,function(){var e,t,n,c,p,v,y=this;return o(this,function(g){switch(g.label){case 0:if(f)throw new Error("Blazor has already started.");return f=!0,d.setEventDispatcher(function(e,t){return DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","DispatchEvent",e,JSON.stringify(t))}),e=a.setPlatform(i.monoPlatform),window.Blazor.platform=e,window.Blazor._internal.renderBatch=function(e,t){u.renderBatch(e,new s.SharedMemoryRenderBatch(t))},window.Blazor._internal.navigationManager.listenForNavigationEvents(function(e,t){return r(y,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,DotNet.invokeMethodAsync("Microsoft.AspNetCore.Blazor","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}})})}),[4,m()];case 1:t=g.sent(),n=function(e){var t=e.cssReferences.map(function(e){var t=document.createElement("link");return t.rel="stylesheet",t.href=e,h(t)}),n=e.jsReferences.map(function(e){var t=document.createElement("script");return t.src=e,h(t)});return Promise.all(t.concat(n))}(t),t.linkerEnabled||console.info("Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414"),c=[t.main].concat(t.assemblyReferences).map(function(e){return"_framework/_bin/"+e}),g.label=2;case 2:return g.trys.push([2,4,,5]),[4,e.start(c)];case 3:return g.sent(),[3,5];case 4:throw p=g.sent(),new Error("Failed to start platform. Reason: "+p);case 5:return[4,n];case 6:return g.sent(),v=l.getAssemblyNameFromUrl(t.main),e.callEntryPoint(v,t.entryPoint,[]),[2]}})})}function m(){return r(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,fetch("_framework/blazor.boot.json",{method:"Get",credentials:"include"})];case 1:return[2,e.sent().json()]}})})}function h(e){return new Promise(function(t,n){e.onload=t,e.onerror=n,document.head.appendChild(e)})}window.Blazor.start=p,c.shouldAutoStart()&&p()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o,a,i,l,u,s=n(32),c=n(49),d=n(33),f={},p={},m={},h="appBinDir",v=Math.pow(2,32),y=Math.pow(2,21)-1;function g(e,t,n){var a="["+e+"]"+t+"."+n,i=p[a];if(!i){if(!(i=o(function(e){var t=f[e];if(!t){if(!(t=r(e)))throw new Error('Could not find assembly "'+e+'"');f[e]=t}return t}(e),t,n)))throw new Error('Could not find type "'+n+'" in namespace "'+t+'" in assembly "'+e+'"');p[a]=i}return i}function b(e,t,n,r){var o="["+e+"]"+t+"."+n+"::"+r,i=m[o];if(!i){if(!(i=a(g(e,t,n),r,-1)))throw new Error('Could not find method "'+r+'" on type "'+t+"."+n+'"');m[o]=i}return i}t.monoPlatform={start:function(e){return new Promise(function(n,f){var p,m;c.attachDebuggerHotkey(e),window.Browser={init:function(){}},p=function(){window.Module=function(e,n,f){var p={},m=["DEBUGGING ENABLED"];return p.print=function(e){return m.indexOf(e)<0&&console.log("WASM: "+e)},p.printErr=function(e){console.error("WASM: "+e),d.showErrorNotification()},p.preRun=[],p.postRun=[],p.preloadPlugins=[],p.locateFile=function(e){switch(e){case"dotnet.wasm":return"_framework/wasm/dotnet.wasm";default:return e}},p.preRun.push(function(){var t=Module.cwrap("mono_wasm_add_assembly",null,["string","number","number"]);r=Module.cwrap("mono_wasm_assembly_load","number",["string"]),o=Module.cwrap("mono_wasm_assembly_find_class","number",["number","string","string"]),a=Module.cwrap("mono_wasm_assembly_find_method","number",["number","string","number"]),i=Module.cwrap("mono_wasm_invoke_method","number",["number","number","number"]),l=Module.cwrap("mono_wasm_string_get_utf8","number",["number"]),u=Module.cwrap("mono_wasm_string_from_js","number",["string"]),MONO.loaded_files=[],e.forEach(function(e){var n=s.getFileNameFromUrl(e),r="blazor:"+n;addRunDependency(r),function(e){return new Promise(function(t,n){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){if(200==r.status||0==r.status&&r.response){var e=new Uint8Array(r.response);t(e)}else n(r)},r.onerror=n,r.send(void 0)})}(e).then(function(o){var a,i=Module._malloc(o.length);new Uint8Array(Module.HEAPU8.buffer,i,o.length).set(o),t(n,i,o.length),MONO.loaded_files.push((a=e,w.href=a,w.href)),removeRunDependency(r)},function(e){e instanceof XMLHttpRequest&&404===e.status&&n.match(/\.pdb$/)||f(e),removeRunDependency(r)})})}),p.postRun.push(function(){var e,r,o;MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE","true"),Module.cwrap("mono_wasm_load_runtime",null,["string","number"])(h,c.hasDebuggingEnabled()?1:0),MONO.mono_wasm_runtime_is_ready=!0,e=b("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","InvokeDotNet"),r=b("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","BeginInvokeDotNet"),o=b("Mono.WebAssembly.Interop","Mono.WebAssembly.Interop","MonoWebAssemblyJSRuntime","EndInvokeJS"),DotNet.attachDispatcher({beginInvokeDotNetFromJS:function(e,n,o,a,i){if(!a&&!n)throw new Error("Either assemblyName or dotNetObjectId must have a non null value.");var l=a?a.toString():n;t.monoPlatform.callMethod(r,null,[e?t.monoPlatform.toDotNetString(e.toString()):null,t.monoPlatform.toDotNetString(l),t.monoPlatform.toDotNetString(o),t.monoPlatform.toDotNetString(i)])},endInvokeJSFromDotNet:function(e,n,r){t.monoPlatform.callMethod(o,null,[t.monoPlatform.toDotNetString(r)])},invokeDotNetFromJS:function(n,r,o,a){var i=t.monoPlatform.callMethod(e,null,[n?t.monoPlatform.toDotNetString(n):null,t.monoPlatform.toDotNetString(r),o?t.monoPlatform.toDotNetString(o.toString()):null,t.monoPlatform.toDotNetString(a)]);return i?t.monoPlatform.toJavaScriptString(i):null}}),n()}),p}(e,n,f),function(){if("undefined"==typeof WebAssembly||!WebAssembly.validate)throw new Error("This browser does not support WebAssembly.");var e=document.createElement("script");e.src="_framework/wasm/dotnet.js",e.defer=!0,document.body.appendChild(e)}()},m=document.createElement("script"),window.__wasmmodulecallback__=p,m.type="text/javascript",m.text="var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;",document.body.appendChild(m)})},findMethod:b,callEntryPoint:function(e,n,r){var o=n.split("::");if(2!=o.length)throw new Error("Malformed entry point method name; could not resolve class name and method name.");var a=o[0],i=o[1],l=a.lastIndexOf("."),u=l>-1?a.substring(0,l):"",s=l>-1?a.substring(l+1):a,c=t.monoPlatform.findMethod(e,u,s,i);t.monoPlatform.callMethod(c,null,r)},callMethod:function(e,n,r){if(r.length>4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u<r.length;++u)Module.setValue(a+4*u,r[u],"i32");Module.setValue(l,0,"i32");var s=i(e,n,a,l);if(0!==Module.getValue(l,"i32"))throw new Error(t.monoPlatform.toJavaScriptString(s));return s}finally{Module.stackRestore(o)}},toJavaScriptString:function(e){var t=l(e),n=Module.UTF8ToString(t);return Module._free(t),n},toDotNetString:function(e){return u(e)},toUint8Array:function(e){var t=E(e),n=Module.getValue(t,"i32");return new Uint8Array(Module.HEAPU8.buffer,t+4,n)},getArrayLength:function(e){return Module.getValue(E(e),"i32")},getArrayEntryPtr:function(e,t,n){return E(e)+4+t*n},getObjectFieldsBaseAddress:function(e){return e+8},readInt16Field:function(e,t){return Module.getValue(e+(t||0),"i16")},readInt32Field:function(e,t){return Module.getValue(e+(t||0),"i32")},readUint64Field:function(e,t){var n=e+(t||0)>>2,r=Module.HEAPU32[n+1];if(r>y)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*v+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var w=document.createElement("a");function E(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(32),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(17),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index cf637d8444bf..321a708f579d 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -13,7 +13,7 @@ export const monoPlatform: Platform = { return new Promise<void>((resolve, reject) => { attachDebuggerHotkey(loadAssemblyUrls); - // mono.js assumes the existence of this + // dotnet.js assumes the existence of this window['Browser'] = { init: () => { }, }; @@ -118,7 +118,7 @@ function addScriptTagsToDocument() { } const scriptElem = document.createElement('script'); - scriptElem.src = '_framework/wasm/mono.js'; + scriptElem.src = '_framework/wasm/dotnet.js'; scriptElem.defer = true; document.body.appendChild(scriptElem); } @@ -142,7 +142,7 @@ function addGlobalModuleScriptTagsToDocument(callback: () => void) { function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () => void, onError: (reason?: any) => void) { const module = {} as typeof Module; - const wasmBinaryFile = '_framework/wasm/mono.wasm'; + const wasmBinaryFile = '_framework/wasm/dotnet.wasm'; const suppressMessages = ['DEBUGGING ENABLED']; module.print = line => (suppressMessages.indexOf(line) < 0 && console.log(`WASM: ${line}`)); @@ -157,7 +157,7 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () module.locateFile = fileName => { switch (fileName) { - case 'mono.wasm': return wasmBinaryFile; + case 'dotnet.wasm': return wasmBinaryFile; default: return fileName; } }; diff --git a/src/Components/test/E2ETest/Tests/MonoSanityTest.cs b/src/Components/test/E2ETest/Tests/MonoSanityTest.cs index 1fb1b26ec903..b8db27fd2b21 100644 --- a/src/Components/test/E2ETest/Tests/MonoSanityTest.cs +++ b/src/Components/test/E2ETest/Tests/MonoSanityTest.cs @@ -74,14 +74,6 @@ public void CanReceiveDotNetExceptionInJavaScript() Assert.Contains("Hello from test", GetValue(Browser, "triggerExceptionMessageStackTrace")); } - [Fact] - public void ProvidesDiagnosticIfInvokingWipedMethod() - { - Browser.FindElement(By.CssSelector("#invokeWipedMethod button")).Click(); - - Assert.Contains("System.NotImplementedException: Cannot invoke method because it was wiped. See stack trace for details.", GetValue(Browser, "invokeWipedMethodStackTrace")); - } - [Fact] public void CanCallJavaScriptFromDotNet() { From 0f2e88a334b89d247f64c84a5c6f4730ff847754 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav B <ajbaaska@microsoft.com> Date: Tue, 21 Jan 2020 12:45:25 -0800 Subject: [PATCH 051/322] Added launchSettings.json for Blazor wasm templates (#18368) * Added launchSettings.json for Blazor wasm templates * Updated launchSettings * removed windows auth option --- .../Client/Properties/launchSettings.json | 3 ++ .../Server/Properties/launchSettings.json | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Properties/launchSettings.json create mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Properties/launchSettings.json diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Properties/launchSettings.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Properties/launchSettings.json new file mode 100644 index 000000000000..5b741f29135a --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Properties/launchSettings.json @@ -0,0 +1,3 @@ +{ + "useWebAssemblyDebugging": true +} \ No newline at end of file diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Properties/launchSettings.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Properties/launchSettings.json new file mode 100644 index 000000000000..3cf9f85e48c0 --- /dev/null +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Properties/launchSettings.json @@ -0,0 +1,36 @@ +{ + "useWebAssemblyDebugging": true, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:8080", + //#if(RequiresHttps) + "sslPort": 44300 + //#else + "sslPort": 0 + //#endif + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.WebApplication1": { + "commandName": "Project", + "launchBrowser": true, + //#if(RequiresHttps) + "applicationUrl": "https://localhost:5001;http://localhost:5000", + //#else + "applicationUrl": "http://localhost:5000", + //#endif + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } + } From 05f2430bbd5e7b6929d5bae69dcdba0cb3c06e32 Mon Sep 17 00:00:00 2001 From: Steve Sanderson <SteveSandersonMS@users.noreply.github.com> Date: Tue, 21 Jan 2020 21:33:27 +0000 Subject: [PATCH 052/322] Update Mono debug proxy code (#18478) --- .../src/MonoDebugProxy/ws-proxy/DebugStore.cs | 4 +- .../src/MonoDebugProxy/ws-proxy/MonoProxy.cs | 139 ++++++++++-------- .../src/MonoDebugProxy/ws-proxy/WsProxy.cs | 48 ++++-- 3 files changed, 116 insertions(+), 75 deletions(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs index ee28bd94b76d..e1e9b7392ba8 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs @@ -545,7 +545,7 @@ public AssemblyInfo GetAssemblyByName (string name) return assemblies.FirstOrDefault (a => a.Name.Equals (name, StringComparison.InvariantCultureIgnoreCase)); } - /* + /* V8 uses zero based indexing for both line and column. PPDBs uses one based indexing for both line and column. */ @@ -598,7 +598,7 @@ public List<SourceLocation> FindPossibleBreakpoints (SourceLocation start, Sourc PPDBs uses one based indexing for both line and column. */ static bool Match (SequencePoint sp, int line, int column) - { + { var bp = (line: line + 1, column: column + 1); if (sp.StartLine > bp.line || sp.EndLine < bp.line) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs index 8c440da1ce24..dfcb373afe38 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs @@ -223,7 +223,7 @@ async Task OnRuntimeReady (CancellationToken token) Info ("RUNTIME READY, PARTY TIME"); await RuntimeReady (token); await SendCommand ("Debugger.resume", new JObject (), token); - SendEvent ("Mono.runtimeReady", new JObject (), token); + SendEvent ("Mono.runtimeReady", new JObject (), token); } async Task OnBreakPointHit (JObject args, CancellationToken token) @@ -274,12 +274,18 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) var frames = new List<Frame> (); int frame_id = 0; var the_mono_frames = res.Value? ["result"]? ["value"]? ["frames"]?.Values<JObject> (); + foreach (var mono_frame in the_mono_frames) { var il_pos = mono_frame ["il_pos"].Value<int> (); var method_token = mono_frame ["method_token"].Value<int> (); var assembly_name = mono_frame ["assembly_name"].Value<string> (); var asm = store.GetAssemblyByName (assembly_name); + if (asm == null) { + Info ($"Unable to find assembly: {assembly_name}"); + continue; + } + var method = asm.GetMethodByToken (method_token); if (method == null) { @@ -374,7 +380,7 @@ async Task OnDefaultContext (int ctx_id, JObject aux_data, CancellationToken tok //Debug ($"\t{is_ready}"); if (is_ready.HasValue && is_ready.Value == true) { Debug ("RUNTIME LOOK READY. GO TIME!"); - await RuntimeReady (token); + await OnRuntimeReady (token); } } @@ -426,33 +432,38 @@ async Task GetDetails(int msg_id, int object_id, CancellationToken token, string return; } - var values = res.Value?["result"]?["value"]?.Values<JObject>().ToArray(); + try { + var values = res.Value?["result"]?["value"]?.Values<JObject>().ToArray() ?? Array.Empty<JObject>(); + var var_list = new List<JObject>(); + + // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously + // results in a "Memory access out of bounds", causing 'values' to be null, + // so skip returning variable values in that case. + for (int i = 0; i < values.Length; i+=2) + { + string fieldName = (string)values[i]["name"]; + if (fieldName.Contains("k__BackingField")){ + fieldName = fieldName.Replace("k__BackingField", ""); + fieldName = fieldName.Replace("<", ""); + fieldName = fieldName.Replace(">", ""); + } + var value = values [i + 1]? ["value"]; + if (((string)value ["description"]) == null) + value ["description"] = value ["value"]?.ToString (); - var var_list = new List<JObject>(); - - // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously - // results in a "Memory access out of bounds", causing 'values' to be null, - // so skip returning variable values in that case. - for (int i = 0; i < values.Length; i+=2) - { - string fieldName = (string)values[i]["name"]; - if (fieldName.Contains("k__BackingField")){ - fieldName = fieldName.Replace("k__BackingField", ""); - fieldName = fieldName.Replace("<", ""); - fieldName = fieldName.Replace(">", ""); - } - var_list.Add(JObject.FromObject(new - { - name = fieldName, - value = values[i+1]["value"] - })); + var_list.Add(JObject.FromObject(new { + name = fieldName, + value + })); + } + o = JObject.FromObject(new + { + result = var_list + }); + } catch (Exception e) { + Debug ($"failed to parse {res.Value}"); } - o = JObject.FromObject(new - { - result = var_list - }); - SendResponse(msg_id, Result.Ok(o), token); } @@ -481,41 +492,51 @@ async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token return; } - var values = res.Value? ["result"]? ["value"]?.Values<JObject> ().ToArray (); - - var var_list = new List<JObject> (); - int i = 0; - // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously - // results in a "Memory access out of bounds", causing 'values' to be null, - // so skip returning variable values in that case. - while (values != null && i < vars.Length && i < values.Length) { - var value = values [i] ["value"]; - if (((string)value ["description"]) == null) - value ["description"] = value ["value"]?.ToString(); - - var_list.Add (JObject.FromObject (new { - name = vars [i].Name, - value = values [i] ["value"] - })); - i++; + try { + var values = res.Value? ["result"]? ["value"]?.Values<JObject> ().ToArray (); + + var var_list = new List<JObject> (); + int i = 0; + // Trying to inspect the stack frame for DotNetDispatcher::InvokeSynchronously + // results in a "Memory access out of bounds", causing 'values' to be null, + // so skip returning variable values in that case. + while (values != null && i < vars.Length && i < values.Length) { + var value = values [i] ["value"]; + if (((string)value ["description"]) == null) + value ["description"] = value ["value"]?.ToString (); + + var_list.Add (JObject.FromObject (new { + name = vars [i].Name, + value + })); + i++; + } + //Async methods are special in the way that local variables can be lifted to generated class fields + //value of "this" comes here either + while (i < values.Length) { + String name = values [i] ["name"].ToString (); + + if (name.IndexOf (">", StringComparison.Ordinal) > 0) + name = name.Substring (1, name.IndexOf (">", StringComparison.Ordinal) - 1); + + var value = values [i + 1] ["value"]; + if (((string)value ["description"]) == null) + value ["description"] = value ["value"]?.ToString (); + + var_list.Add (JObject.FromObject (new { + name, + value + })); + i = i + 2; + } + o = JObject.FromObject (new { + result = var_list + }); + SendResponse (msg_id, Result.Ok (o), token); } - //Async methods are special in the way that local variables can be lifted to generated class fields - //value of "this" comes here either - while (i < values.Length) { - String name = values [i] ["name"].ToString (); - - if (name.IndexOf (">", StringComparison.Ordinal) > 0) - name = name.Substring (1, name.IndexOf (">", StringComparison.Ordinal) - 1); - var_list.Add (JObject.FromObject (new { - name = name, - value = values [i+1] ["value"] - })); - i = i + 2; + catch (Exception exc) { + SendResponse (msg_id, res, token); } - o = JObject.FromObject (new { - result = var_list - }); - SendResponse (msg_id, Result.Ok (o), token); } async Task<Result> EnableBreakPoint (Breakpoint bp, CancellationToken token) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs index 17c72e9ce781..87ef23027e8a 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs @@ -97,6 +97,7 @@ public Task Pump (CancellationToken token) internal class WsProxy { TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool> (); + TaskCompletionSource<bool> client_initiated_close = new TaskCompletionSource<bool> (); List<(int, TaskCompletionSource<Result>)> pending_cmds = new List<(int, TaskCompletionSource<Result>)> (); ClientWebSocket browser; WebSocket ide; @@ -119,8 +120,16 @@ async Task<string> ReadOne (WebSocket socket, CancellationToken token) byte [] buff = new byte [4000]; var mem = new MemoryStream (); while (true) { + + if (socket.State != WebSocketState.Open) { + Console.WriteLine ($"WSProxy: Socket is no longer open."); + client_initiated_close.TrySetResult (true); + return null; + } + var result = await socket.ReceiveAsync (new ArraySegment<byte> (buff), token); if (result.MessageType == WebSocketMessageType.Close) { + client_initiated_close.TrySetResult (true); return null; } @@ -144,7 +153,7 @@ WsQueue GetQueueForTask (Task task) { void Send (WebSocket to, JObject o, CancellationToken token) { - var bytes = Encoding.UTF8.GetBytes (o.ToString ()); + var bytes = Encoding.UTF8.GetBytes (o.ToString ()); var queue = GetQueueForSocket (to); var task = queue.Send (bytes, token); @@ -199,9 +208,10 @@ void ProcessBrowserMessage (string msg, CancellationToken token) void ProcessIdeMessage (string msg, CancellationToken token) { - var res = JObject.Parse (msg); - - pending_ops.Add (OnCommand (res ["id"].Value<int> (), res ["method"].Value<string> (), res ["params"] as JObject, token)); + if (!string.IsNullOrEmpty (msg)) { + var res = JObject.Parse (msg); + pending_ops.Add (OnCommand (res ["id"].Value<int> (), res ["method"].Value<string> (), res ["params"] as JObject, token)); + } } internal async Task<Result> SendCommand (string method, JObject args, CancellationToken token) { @@ -255,24 +265,25 @@ void SendResponseInternal (int id, Result result, CancellationToken token) Send (this.ide, o, token); } - // , HttpContext context) + // , HttpContext context) public async Task Run (Uri browserUri, WebSocket ideSocket) { - Debug ("wsproxy start"); + Debug ($"WsProxy Starting on {browserUri}"); using (this.ide = ideSocket) { - Debug ("ide connected"); + Debug ($"WsProxy: IDE waiting for connection on {browserUri}"); queues.Add (new WsQueue (this.ide)); using (this.browser = new ClientWebSocket ()) { this.browser.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan; await this.browser.ConnectAsync (browserUri, CancellationToken.None); queues.Add (new WsQueue (this.browser)); - Debug ("client connected"); + Debug ($"WsProxy: Client connected on {browserUri}"); var x = new CancellationTokenSource (); pending_ops.Add (ReadOne (browser, x.Token)); pending_ops.Add (ReadOne (ide, x.Token)); pending_ops.Add (side_exception.Task); + pending_ops.Add (client_initiated_close.Task); try { while (!x.IsCancellationRequested) { @@ -280,15 +291,23 @@ public async Task Run (Uri browserUri, WebSocket ideSocket) //Console.WriteLine ("pump {0} {1}", task, pending_ops.IndexOf (task)); if (task == pending_ops [0]) { var msg = ((Task<string>)task).Result; - pending_ops [0] = ReadOne (browser, x.Token); //queue next read - ProcessBrowserMessage (msg, x.Token); + if (msg != null) { + pending_ops [0] = ReadOne (browser, x.Token); //queue next read + ProcessBrowserMessage (msg, x.Token); + } } else if (task == pending_ops [1]) { var msg = ((Task<string>)task).Result; - pending_ops [1] = ReadOne (ide, x.Token); //queue next read - ProcessIdeMessage (msg, x.Token); + if (msg != null) { + pending_ops [1] = ReadOne (ide, x.Token); //queue next read + ProcessIdeMessage (msg, x.Token); + } } else if (task == pending_ops [2]) { var res = ((Task<bool>)task).Result; throw new Exception ("side task must always complete with an exception, what's going on???"); + } else if (task == pending_ops [3]) { + var res = ((Task<bool>)task).Result; + Debug ($"WsProxy: Client initiated close from {browserUri}"); + x.Cancel (); } else { //must be a background task pending_ops.Remove (task); @@ -301,10 +320,11 @@ public async Task Run (Uri browserUri, WebSocket ideSocket) } } } catch (Exception e) { - Debug ($"got exception {e}"); + Debug ($"WsProxy::Run: Exception {e}"); //throw; } finally { - x.Cancel (); + if (!x.IsCancellationRequested) + x.Cancel (); } } } From 41bc4ec1296e41bf37a7f972864ed25c91152ae6 Mon Sep 17 00:00:00 2001 From: wtgodbe <wigodbe@microsoft.com> Date: Tue, 21 Jan 2020 14:35:16 -0800 Subject: [PATCH 053/322] Fix logic for _GetPackageVersionInfo --- Directory.Build.targets | 7 +++++++ eng/targets/Packaging.targets | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index db3cea59f118..70c1ab16cd0c 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -70,6 +70,10 @@ <IsPackable Condition=" '$(IsPackageInThisPatch)' != 'true' ">false</IsPackable> </PropertyGroup> + <PropertyGroup> + <PackageVersionForPackageVersionInfo>$(PackageVersion)</PackageVersionForPackageVersionInfo> + </PropertyGroup> + <PropertyGroup Condition=" '$(IsPackageInThisPatch)' != 'true' AND '$(BaselinePackageVersion)' != '' AND '$(IsServicingBuild)' == 'true' "> <!-- This keeps assembly and package versions consistent across patches. If a package is not included in a patch, its version should stay at the baseline. --> <AssemblyVersion Condition="$(BaselinePackageVersion.Contains('-'))">$(BaselinePackageVersion.Substring(0, $(BaselinePackageVersion.IndexOf('-')))).0</AssemblyVersion> @@ -83,6 +87,9 @@ --> <Version Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</Version> <PackageVersion Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</PackageVersion> + + <!-- For servicing builds, we want to resolve basline versions of project packages that aren't building, always --> + <PackageVersionForPackageVersionInfo>$(BaselinePackageVersion)</PackageVersionForPackageVersionInfo> </PropertyGroup> <PropertyGroup> diff --git a/eng/targets/Packaging.targets b/eng/targets/Packaging.targets index fdef1de7a324..ea8dabdb4675 100644 --- a/eng/targets/Packaging.targets +++ b/eng/targets/Packaging.targets @@ -13,7 +13,7 @@ <ItemGroup> <_ProjectPathWithVersion Include="$(MSBuildProjectFullPath)"> <PackageId>$(PackageId)</PackageId> - <PackageVersion>$(PackageVersion)</PackageVersion> + <PackageVersion>$(PackageVersionForPackageVersionInfo)</PackageVersion> <VersionSuffix>$(VersionSuffix)</VersionSuffix> <VersionVariableName>$(PackageId.Replace('.',''))PackageVersion</VersionVariableName> </_ProjectPathWithVersion> From 419a1f11a9a94047c82e728693e0e62d146befb8 Mon Sep 17 00:00:00 2001 From: wtgodbe <wigodbe@microsoft.com> Date: Tue, 21 Jan 2020 14:38:56 -0800 Subject: [PATCH 054/322] Undo accidental merge --- Directory.Build.targets | 7 ------- eng/targets/Packaging.targets | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 70c1ab16cd0c..db3cea59f118 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -70,10 +70,6 @@ <IsPackable Condition=" '$(IsPackageInThisPatch)' != 'true' ">false</IsPackable> </PropertyGroup> - <PropertyGroup> - <PackageVersionForPackageVersionInfo>$(PackageVersion)</PackageVersionForPackageVersionInfo> - </PropertyGroup> - <PropertyGroup Condition=" '$(IsPackageInThisPatch)' != 'true' AND '$(BaselinePackageVersion)' != '' AND '$(IsServicingBuild)' == 'true' "> <!-- This keeps assembly and package versions consistent across patches. If a package is not included in a patch, its version should stay at the baseline. --> <AssemblyVersion Condition="$(BaselinePackageVersion.Contains('-'))">$(BaselinePackageVersion.Substring(0, $(BaselinePackageVersion.IndexOf('-')))).0</AssemblyVersion> @@ -87,9 +83,6 @@ --> <Version Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</Version> <PackageVersion Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</PackageVersion> - - <!-- For servicing builds, we want to resolve basline versions of project packages that aren't building, always --> - <PackageVersionForPackageVersionInfo>$(BaselinePackageVersion)</PackageVersionForPackageVersionInfo> </PropertyGroup> <PropertyGroup> diff --git a/eng/targets/Packaging.targets b/eng/targets/Packaging.targets index ea8dabdb4675..fdef1de7a324 100644 --- a/eng/targets/Packaging.targets +++ b/eng/targets/Packaging.targets @@ -13,7 +13,7 @@ <ItemGroup> <_ProjectPathWithVersion Include="$(MSBuildProjectFullPath)"> <PackageId>$(PackageId)</PackageId> - <PackageVersion>$(PackageVersionForPackageVersionInfo)</PackageVersion> + <PackageVersion>$(PackageVersion)</PackageVersion> <VersionSuffix>$(VersionSuffix)</VersionSuffix> <VersionVariableName>$(PackageId.Replace('.',''))PackageVersion</VersionVariableName> </_ProjectPathWithVersion> From ba08d60cb95c01e8de4ebeda3948217fcc6b24a8 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 21 Jan 2020 14:43:34 -0800 Subject: [PATCH 055/322] Update names and descriptions for benchmarks (#18430) --- .../Driver/BenchmarkResult.cs | 11 ++++++ .../Wasm.Performance/Driver/Program.cs | 10 ++--- .../TestApp/wwwroot/benchmarks/appStartup.js | 5 +++ .../wwwroot/benchmarks/jsonHandling.js | 38 +++++++++++++++++-- .../benchmarks/lib/minibench/minibench.js | 16 ++++++-- .../TestApp/wwwroot/benchmarks/renderList.js | 21 ++++++++-- .../Wasm.Performance/benchmarks.compose.json | 3 ++ 7 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs index 3173341e4b86..33e4c4094bdd 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResult.cs @@ -4,10 +4,21 @@ class BenchmarkResult { public string Name { get; set; } + public BenchmarkDescriptor Descriptor { get; set; } + + public string ShortDescription { get; set; } + public bool Success { get; set; } public int NumExecutions { get; set; } public double Duration { get; set; } + + public class BenchmarkDescriptor + { + public string Name { get; set; } + + public string Description { get; set; } + } } } \ No newline at end of file diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index cfaa9cef0fc9..0d74c8c6b7cc 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -76,9 +76,9 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) output.Metadata.Add(new BenchmarkMetadata { Source = "BlazorWasm", - Name = result.Name, - ShortDescription = $"{result.Name} Duration", - LongDescription = $"{result.Name} Duration", + Name = result.Descriptor.Name, + ShortDescription = result.Name, + LongDescription = result.Descriptor.Description, Format = "n2" }); @@ -94,7 +94,7 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) output.Metadata.Add(new BenchmarkMetadata { Source = "BlazorWasm", - Name = "Publish size", + Name = "blazorwasm/publish-size", ShortDescription = "Publish size (KB)", LongDescription = "Publish size (KB)", Format = "n2", @@ -116,7 +116,7 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) output.Metadata.Add(new BenchmarkMetadata { Source = "BlazorWasm", - Name = "Publish size (compressed)", + Name = "blazorwasm/compressed-publish-size", ShortDescription = "Publish size compressed app (KB)", LongDescription = "Publish size - compressed app (KB)", Format = "n2", diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js index 4f11b64b0f62..f506b12ee429 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/appStartup.js @@ -10,6 +10,11 @@ group('App Startup', () => { } finally { app.dispose(); } + }, { + descriptor: { + name: "blazorwasm/time-to-first-ui", + description: "Time to render first UI (ms)" + } }); }); diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js index 4f6a31115202..698eb7cee5ca 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/jsonHandling.js @@ -16,22 +16,47 @@ group('JSON handling', () => { teardown(() => app.dispose()); benchmark('Serialize 1kb', () => - benchmarkJson(app, '#serialize-small', '#serialized-length', 935)); + benchmarkJson(app, '#serialize-small', '#serialized-length', 935), { + descriptor: { + name: 'blazorwasm/jsonserialize-1kb', + description: 'Serialize JSON 1kb - Time in ms' + } + }); benchmark('Serialize 340kb', () => - benchmarkJson(app, '#serialize-large', '#serialized-length', 339803)); + benchmarkJson(app, '#serialize-large', '#serialized-length', 339803), { + descriptor: { + name: 'blazorwasm/jsonserialize-340kb', + description: 'Serialize JSON 340kb - Time in ms' + } + }); benchmark('Deserialize 1kb', () => - benchmarkJson(app, '#deserialize-small', '#deserialized-count', 5)); + benchmarkJson(app, '#deserialize-small', '#deserialized-count', 5), { + descriptor: { + name: 'blazorwasm/jsondeserialize-1kb', + description: 'Deserialize JSON 1kb - Time in ms' + } + }); benchmark('Deserialize 340kb', () => - benchmarkJson(app, '#deserialize-large', '#deserialized-count', 1365)); + benchmarkJson(app, '#deserialize-large', '#deserialized-count', 1365), { + descriptor: { + name: 'blazorwasm/jsondeserialize-340kb', + description: 'Deserialize JSON 340kb - Time in ms' + } + }); benchmark('Serialize 340kb (JavaScript)', () => { const json = JSON.stringify(largeObjectToSerialize); if (json.length !== 339803) { throw new Error(`Incorrect length: ${json.length}`); } + }, { + descriptor: { + name: 'blazorwasm/jsonserialize-javascript-340kb', + description: 'Serialize JSON 340kb using JavaScript - Time in ms' + } }); benchmark('Deserialize 340kb (JavaScript)', () => { @@ -39,6 +64,11 @@ group('JSON handling', () => { if (parsed.name !== 'CEO - Subordinate 0') { throw new Error('Incorrect result'); } + }, { + descriptor: { + name: 'blazorwasm/jsondeserialize-javascript-340kb', + description: 'Deserialize JSON 340kb using JavaScript - Time in ms' + } }); }); diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js index 241721ceeb13..f331321ad0fb 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/lib/minibench/minibench.js @@ -165,7 +165,7 @@ class Benchmark extends EventEmitter { this._group = group; this.name = name; this._fn = fn; - this._options = options; + this._options = options || {}; this._state = { status: BenchmarkStatus.idle }; } @@ -205,13 +205,23 @@ class Benchmark extends EventEmitter { await this._group.runTeardown(); } - reportBenchmarkEvent(BenchmarkEvent.benchmarkCompleted, { 'name': this.name, success: true, numExecutions: this._state.numExecutions, duration: this._state.estimatedExecutionDurationMs }); + reportBenchmarkEvent(BenchmarkEvent.benchmarkCompleted, { + name: this.name, + success: true, + numExecutions: this._state.numExecutions, + duration: this._state.estimatedExecutionDurationMs, + descriptor: this._options.descriptor + }); this._updateState({ status: BenchmarkStatus.idle }); } catch (ex) { this._updateState({ status: BenchmarkStatus.error }); console.error(ex); - reportBenchmarkEvent(BenchmarkEvent.benchmarkError, { 'name': this.name, success: false }); + reportBenchmarkEvent(BenchmarkEvent.benchmarkError, { + name: this.name, + success: false, + descriptor: this._options.descriptor + }); } }); } diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js index 68bf32d747c1..32a1bb8a7282 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/wwwroot/benchmarks/renderList.js @@ -16,9 +16,24 @@ group('Rendering list', () => { app.dispose(); }); - benchmark('Render 10 items', () => measureRenderList(app, 10)); - benchmark('Render 100 items', () => measureRenderList(app, 100)); - benchmark('Render 1000 items', () => measureRenderList(app, 1000)); + benchmark('Render 10 items', () => measureRenderList(app, 10), { + descriptor: { + name: 'blazorwasm/render-10-items', + description: 'Time to render 10 item list (ms)' + } + }); + benchmark('Render 100 items', () => measureRenderList(app, 100), { + descriptor: { + name: 'blazorwasm/render-100-items', + description: 'Time to render 100 item list (ms)' + } + }); + benchmark('Render 1000 items', () => measureRenderList(app, 1000), { + descriptor: { + name: 'blazorwasm/render-1000-items', + description: 'Time to render 1000 item list (ms)' + } + }); }); diff --git a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json index 81607364dc6f..442346e79cd7 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json +++ b/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json @@ -14,6 +14,9 @@ "branchOrCommit": "blazor-wasm", "dockerfile": "src/Components/benchmarkapps/Wasm.Performance/dockerfile" }, + "buildArguments": [ + "gitBranch=blazor-wasm" + ], "waitForExit": true, "readyStateText": "Application started." } From 3111032dc074a252f1d1cbd951ecb41153bd1555 Mon Sep 17 00:00:00 2001 From: Ryan Nowak <nowakra@gmail.com> Date: Sun, 19 Jan 2020 15:51:50 -0800 Subject: [PATCH 056/322] Rework of Blazor startup experience Fixes: #16874 This is a significant simplication of our startup code model for Blazor wasm with the goal of removing concepts that don't make much sense here. Previously in this area we've tried to be consistent with ASP.NET Core on the server, but it's not helping up much in WASM. We're still leveraging some of the lessons from server-size ASP.NET (hello CreateDefaultBuilder) but consistency is no longer a goal. This change actually makes a bunch of scenarios better (rather than removing features) - it's now possible to access services from the application's DI scope and initialize them before the UI is shown `RunAsync`. This change also adds configuration in a central way. There's nothing in this change that populates configuration in an automatic way, that will come next. --- .../ref/Microsoft.AspNetCore.Blazor.csproj | 2 +- ...rosoft.AspNetCore.Blazor.netstandard2.1.cs | 62 +++--- .../ComponentsApplicationBuilderExtensions.cs | 24 -- .../Builder/IComponentsApplicationBuilder.cs | 26 --- .../src/Hosting/BlazorWebAssemblyHost.cs | 20 -- .../src/Hosting/ConventionBasedStartup.cs | 117 ---------- .../Blazor/src/Hosting/IBlazorStartup.cs | 16 -- .../Blazor/src/Hosting/IWebAssemblyHost.cs | 34 --- .../src/Hosting/IWebAssemblyHostBuilder.cs | 46 ---- .../IWebAssemblyServiceFactoryAdapter.cs | 17 -- .../src/Hosting/RootComponentMapping.cs | 53 +++++ .../Hosting/RootComponentMappingCollection.cs | 68 ++++++ .../WebAssemblyBlazorApplicationBuilder.cs | 54 ----- .../Blazor/src/Hosting/WebAssemblyHost.cs | 153 ++++++++----- .../src/Hosting/WebAssemblyHostBuilder.cs | 134 ++++++----- .../Hosting/WebAssemblyHostBuilderContext.cs | 27 --- .../WebAssemblyHostBuilderExtensions.cs | 73 ------ .../src/Hosting/WebAssemblyHostExtensions.cs | 36 --- .../WebAssemblyServiceFactoryAdapter.cs | 52 ----- .../src/Microsoft.AspNetCore.Blazor.csproj | 4 +- .../Hosting/ConventionBasedStartupTest.cs | 210 ------------------ .../test/Hosting/RootComponentMappingTest.cs | 37 +++ .../Hosting/WebAssemblyHostBuilderTest.cs | 148 ++++-------- .../test/Hosting/WebAssemblyHostTest.cs | 79 ++++--- .../HostedInAspNet.Client/Program.cs | 12 +- .../HostedInAspNet.Client/Startup.cs | 20 -- .../testassets/StandaloneApp/Program.cs | 12 +- .../testassets/StandaloneApp/Startup.cs | 20 -- .../Wasm.Performance/Driver/Program.cs | 4 +- .../Wasm.Performance/TestApp/Program.cs | 12 +- .../Wasm.Performance/TestApp/Startup.cs | 20 -- .../test/testassets/BasicTestApp/Program.cs | 29 ++- .../test/testassets/BasicTestApp/Startup.cs | 39 ---- .../test/testassets/TestServer/CorsStartup.cs | 4 +- .../TestServer/InternationalizationStartup.cs | 2 +- ...tartupWithMapFallbackToClientSideBlazor.cs | 10 +- .../BlazorWasm-CSharp/Client/Program.cs | 28 ++- .../BlazorWasm-CSharp/Client/Startup.cs | 28 --- .../BlazorWasm-CSharp/Server/Startup.cs | 4 +- 39 files changed, 516 insertions(+), 1220 deletions(-) delete mode 100644 src/Components/Blazor/Blazor/src/Builder/ComponentsApplicationBuilderExtensions.cs delete mode 100644 src/Components/Blazor/Blazor/src/Builder/IComponentsApplicationBuilder.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/ConventionBasedStartup.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/IBlazorStartup.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHost.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHostBuilder.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyServiceFactoryAdapter.cs create mode 100644 src/Components/Blazor/Blazor/src/Hosting/RootComponentMapping.cs create mode 100644 src/Components/Blazor/Blazor/src/Hosting/RootComponentMappingCollection.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/WebAssemblyBlazorApplicationBuilder.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderContext.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderExtensions.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostExtensions.cs delete mode 100644 src/Components/Blazor/Blazor/src/Hosting/WebAssemblyServiceFactoryAdapter.cs delete mode 100644 src/Components/Blazor/Blazor/test/Hosting/ConventionBasedStartupTest.cs create mode 100644 src/Components/Blazor/Blazor/test/Hosting/RootComponentMappingTest.cs delete mode 100644 src/Components/Blazor/testassets/HostedInAspNet.Client/Startup.cs delete mode 100644 src/Components/Blazor/testassets/StandaloneApp/Startup.cs delete mode 100644 src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs delete mode 100644 src/Components/test/testassets/BasicTestApp/Startup.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj index 88ca078caaeb..25d2991601ec 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj @@ -7,6 +7,6 @@ <Compile Include="Microsoft.AspNetCore.Blazor.netstandard2.1.cs" /> <Reference Include="Mono.WebAssembly.Interop" /> <Reference Include="Microsoft.AspNetCore.Components.Web" /> - <Reference Include="Microsoft.Extensions.Options" /> + <Reference Include="Microsoft.Extensions.Configuration" /> </ItemGroup> </Project> diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs index b8062d72c0ee..eb3336297518 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.1.cs @@ -12,38 +12,38 @@ public static void NotifyLocationChanged(string uri, bool isInterceptedLink) { } } namespace Microsoft.AspNetCore.Blazor.Hosting { - public static partial class BlazorWebAssemblyHost + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct RootComponentMapping { - public static Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder CreateDefaultBuilder() { throw null; } + private readonly object _dummy; + public RootComponentMapping(System.Type componentType, string selector) { throw null; } + public System.Type ComponentType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Selector { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } - public partial interface IWebAssemblyHost : System.IDisposable + public partial class RootComponentMappingCollection : System.Collections.ObjectModel.Collection<Microsoft.AspNetCore.Blazor.Hosting.RootComponentMapping> { - System.IServiceProvider Services { get; } - System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); - System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + public RootComponentMappingCollection() { } + public void Add(System.Type componentType, string selector) { } + public void AddRange(System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Blazor.Hosting.RootComponentMapping> items) { } + public void Add<TComponent>(string selector) where TComponent : Microsoft.AspNetCore.Components.IComponent { } } - public partial interface IWebAssemblyHostBuilder + public sealed partial class WebAssemblyHost : System.IAsyncDisposable { - System.Collections.Generic.IDictionary<object, object> Properties { get; } - Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHost Build(); - Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder ConfigureServices(System.Action<Microsoft.AspNetCore.Blazor.Hosting.WebAssemblyHostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceCollection> configureDelegate); - Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder> factory); - Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(System.Func<Microsoft.AspNetCore.Blazor.Hosting.WebAssemblyHostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder>> factory); + internal WebAssemblyHost() { } + public Microsoft.Extensions.Configuration.IConfiguration Configuration { get { throw null; } } + public System.IServiceProvider Services { get { throw null; } } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public System.Threading.Tasks.Task RunAsync() { throw null; } } - public sealed partial class WebAssemblyHostBuilderContext + public sealed partial class WebAssemblyHostBuilder { - public WebAssemblyHostBuilderContext(System.Collections.Generic.IDictionary<object, object> properties) { } - public System.Collections.Generic.IDictionary<object, object> Properties { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public static partial class WebAssemblyHostBuilderExtensions - { - public static Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder ConfigureServices(this Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder hostBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection> configureDelegate) { throw null; } - public static Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder UseBlazorStartup(this Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder builder, System.Type startupType) { throw null; } - public static Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder UseBlazorStartup<TStartup>(this Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHostBuilder builder) { throw null; } - } - public static partial class WebAssemblyHostExtensions - { - public static void Run(this Microsoft.AspNetCore.Blazor.Hosting.IWebAssemblyHost host) { } + internal WebAssemblyHostBuilder() { } + public Microsoft.Extensions.Configuration.IConfigurationBuilder Configuration { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.AspNetCore.Blazor.Hosting.RootComponentMappingCollection RootComponents { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.Extensions.DependencyInjection.IServiceCollection Services { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.AspNetCore.Blazor.Hosting.WebAssemblyHost Build() { throw null; } + public static Microsoft.AspNetCore.Blazor.Hosting.WebAssemblyHostBuilder CreateDefault(string[] args = null) { throw null; } } } namespace Microsoft.AspNetCore.Blazor.Http @@ -67,15 +67,3 @@ public static partial class WebAssemblyEventDispatcher public static System.Threading.Tasks.Task DispatchEvent(Microsoft.AspNetCore.Components.RenderTree.WebEventDescriptor eventDescriptor, string eventArgsJson) { throw null; } } } -namespace Microsoft.AspNetCore.Components.Builder -{ - public static partial class ComponentsApplicationBuilderExtensions - { - public static void AddComponent<TComponent>(this Microsoft.AspNetCore.Components.Builder.IComponentsApplicationBuilder app, string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { } - } - public partial interface IComponentsApplicationBuilder - { - System.IServiceProvider Services { get; } - void AddComponent(System.Type componentType, string domElementSelector); - } -} diff --git a/src/Components/Blazor/Blazor/src/Builder/ComponentsApplicationBuilderExtensions.cs b/src/Components/Blazor/Blazor/src/Builder/ComponentsApplicationBuilderExtensions.cs deleted file mode 100644 index 66532474c636..000000000000 --- a/src/Components/Blazor/Blazor/src/Builder/ComponentsApplicationBuilderExtensions.cs +++ /dev/null @@ -1,24 +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.Builder -{ - /// <summary> - /// Provides extension methods for <see cref="IComponentsApplicationBuilder"/>. - /// </summary> - public static class ComponentsApplicationBuilderExtensions - { - /// <summary> - /// Associates the component type with the application, - /// causing it to be displayed in the specified DOM element. - /// </summary> - /// <param name="app">The <see cref="IComponentsApplicationBuilder"/>.</param> - /// <typeparam name="TComponent">The type of the component.</typeparam> - /// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param> - public static void AddComponent<TComponent>(this IComponentsApplicationBuilder app, string domElementSelector) - where TComponent : IComponent - { - app.AddComponent(typeof(TComponent), domElementSelector); - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Builder/IComponentsApplicationBuilder.cs b/src/Components/Blazor/Blazor/src/Builder/IComponentsApplicationBuilder.cs deleted file mode 100644 index 84806a87697e..000000000000 --- a/src/Components/Blazor/Blazor/src/Builder/IComponentsApplicationBuilder.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components.Builder -{ - /// <summary> - /// A builder for adding components to an application. - /// </summary> - public interface IComponentsApplicationBuilder - { - /// <summary> - /// Gets the application services. - /// </summary> - IServiceProvider Services { get; } - - /// <summary> - /// Associates the <see cref="IComponent"/> with the application, - /// causing it to be displayed in the specified DOM element. - /// </summary> - /// <param name="componentType">The type of the component.</param> - /// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param> - void AddComponent(Type componentType, string domElementSelector); - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs b/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs deleted file mode 100644 index e5631805ef64..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs +++ /dev/null @@ -1,20 +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.Blazor.Hosting -{ - /// <summary> - /// Used to create an instance of Blazor host builder for a Browser application. - /// </summary> - public static class BlazorWebAssemblyHost - { - /// <summary> - /// Creates an instance of <see cref="IWebAssemblyHostBuilder"/>. - /// </summary> - /// <returns>The <see cref="IWebAssemblyHostBuilder"/>.</returns> - public static IWebAssemblyHostBuilder CreateDefaultBuilder() - { - return new WebAssemblyHostBuilder(); - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/ConventionBasedStartup.cs b/src/Components/Blazor/Blazor/src/Hosting/ConventionBasedStartup.cs deleted file mode 100644 index 53eecbf6e08c..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/ConventionBasedStartup.cs +++ /dev/null @@ -1,117 +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.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Runtime.ExceptionServices; -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - // Keeping this simple for now to focus on predictable and reasonable behaviors. - // Startup in WebHost supports lots of things we don't yet support, and some we - // may never support. - // - // Possible additions: - // - environments - // - case-insensitivity (makes sense with environments) - // - // Likely never: - // - statics - // - DI into constructor - internal class ConventionBasedStartup : IBlazorStartup - { - public ConventionBasedStartup(object instance) - { - Instance = instance ?? throw new ArgumentNullException(nameof(instance)); - } - - public object Instance { get; } - - public void Configure(IComponentsApplicationBuilder app, IServiceProvider services) - { - try - { - var method = GetConfigureMethod(); - Debug.Assert(method != null); - - var parameters = method.GetParameters(); - var arguments = new object[parameters.Length]; - for (var i = 0; i < parameters.Length; i++) - { - var parameter = parameters[i]; - arguments[i] = parameter.ParameterType == typeof(IComponentsApplicationBuilder) - ? app - : services.GetRequiredService(parameter.ParameterType); - } - - method.Invoke(Instance, arguments); - } - catch (Exception ex) - { - if (ex is TargetInvocationException) - { - ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); - } - - throw; - } - } - - internal MethodInfo GetConfigureMethod() - { - var methods = Instance.GetType() - .GetMethods(BindingFlags.Instance | BindingFlags.Public) - .Where(m => string.Equals(m.Name, "Configure", StringComparison.Ordinal)) - .ToArray(); - - if (methods.Length == 1) - { - return methods[0]; - } - else if (methods.Length == 0) - { - throw new InvalidOperationException("The startup class must define a 'Configure' method."); - } - else - { - throw new InvalidOperationException("Overloading the 'Configure' method is not supported."); - } - } - - public void ConfigureServices(IServiceCollection services) - { - try - { - var method = GetConfigureServicesMethod(); - if (method != null) - { - method.Invoke(Instance, new object[] { services }); - } - } - catch (Exception ex) - { - if (ex is TargetInvocationException) - { - ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); - } - - throw; - } - } - - internal MethodInfo GetConfigureServicesMethod() - { - return Instance.GetType() - .GetMethod( - "ConfigureServices", - BindingFlags.Public | BindingFlags.Instance, - null, - new Type[] { typeof(IServiceCollection), }, - Array.Empty<ParameterModifier>()); - } - } -} \ No newline at end of file diff --git a/src/Components/Blazor/Blazor/src/Hosting/IBlazorStartup.cs b/src/Components/Blazor/Blazor/src/Hosting/IBlazorStartup.cs deleted file mode 100644 index e87138387f21..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/IBlazorStartup.cs +++ /dev/null @@ -1,16 +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 Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - internal interface IBlazorStartup - { - void ConfigureServices(IServiceCollection services); - - void Configure(IComponentsApplicationBuilder app, IServiceProvider services); - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHost.cs b/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHost.cs deleted file mode 100644 index 8f21f93421bb..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHost.cs +++ /dev/null @@ -1,34 +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.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - /// <summary> - /// A program abstraction. - /// </summary> - public interface IWebAssemblyHost : IDisposable - { - /// <summary> - /// The programs configured services. - /// </summary> - IServiceProvider Services { get; } - - /// <summary> - /// Start the program. - /// </summary> - /// <param name="cancellationToken">Used to abort program start.</param> - /// <returns></returns> - Task StartAsync(CancellationToken cancellationToken = default); - - /// <summary> - /// Attempts to gracefully stop the program. - /// </summary> - /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param> - /// <returns></returns> - Task StopAsync(CancellationToken cancellationToken = default); - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHostBuilder.cs b/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHostBuilder.cs deleted file mode 100644 index c5a52bc280c9..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyHostBuilder.cs +++ /dev/null @@ -1,46 +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 Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - /// <summary> - /// Abstraction for configuring a Blazor browser-based application. - /// </summary> - public interface IWebAssemblyHostBuilder - { - /// <summary> - /// A central location for sharing state between components during the host building process. - /// </summary> - IDictionary<object, object> Properties { get; } - - /// <summary> - /// Overrides the factory used to create the service provider. - /// </summary> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory); - - /// <summary> - /// Overrides the factory used to create the service provider. - /// </summary> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<WebAssemblyHostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory); - - /// <summary> - /// Adds services to the container. This can be called multiple times and the results will be additive. - /// </summary> - /// <param name="configureDelegate">The delegate for configuring the <see cref="IServiceCollection"/> that will be used - /// to construct the <see cref="IServiceProvider"/>.</param> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - IWebAssemblyHostBuilder ConfigureServices(Action<WebAssemblyHostBuilderContext, IServiceCollection> configureDelegate); - - /// <summary> - /// Run the given actions to initialize the host. This can only be called once. - /// </summary> - /// <returns>An initialized <see cref="IWebAssemblyHost"/></returns> - IWebAssemblyHost Build(); - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyServiceFactoryAdapter.cs b/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyServiceFactoryAdapter.cs deleted file mode 100644 index c790a3c8791f..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/IWebAssemblyServiceFactoryAdapter.cs +++ /dev/null @@ -1,17 +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 Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - // Equivalent to https://github.com/aspnet/Extensions/blob/master/src/Hosting/Hosting/src/Internal/IServiceFactoryAdapter.cs - - internal interface IWebAssemblyServiceFactoryAdapter - { - object CreateBuilder(IServiceCollection services); - - IServiceProvider CreateServiceProvider(object containerBuilder); - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/RootComponentMapping.cs b/src/Components/Blazor/Blazor/src/Hosting/RootComponentMapping.cs new file mode 100644 index 000000000000..53b34d882285 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Hosting/RootComponentMapping.cs @@ -0,0 +1,53 @@ +// 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 Microsoft.AspNetCore.Components; + +namespace Microsoft.AspNetCore.Blazor.Hosting +{ + /// <summary> + /// Defines a mapping between a root <see cref="IComponent"/> and a DOM element selector. + /// </summary> + public readonly struct RootComponentMapping + { + /// <summary> + /// Creates a new instance of <see cref="RootComponentMapping"/> with the provided <paramref name="componentType"/> + /// and <paramref name="selector"/>. + /// </summary> + /// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param> + /// <param name="selector">The DOM element selector.</param> + public RootComponentMapping(Type componentType, string selector) + { + if (componentType is null) + { + throw new ArgumentNullException(nameof(componentType)); + } + + if (!typeof(IComponent).IsAssignableFrom(componentType)) + { + throw new ArgumentException( + $"The type '{componentType.Name}' must implement {nameof(IComponent)} to be used as a root component.", + nameof(componentType)); + } + + if (selector is null) + { + throw new ArgumentNullException(nameof(selector)); + } + + ComponentType = componentType; + Selector = selector; + } + + /// <summary> + /// Gets the component type. + /// </summary> + public Type ComponentType { get; } + + /// <summary> + /// Gets the DOM element selector. + /// </summary> + public string Selector { get; } + } +} diff --git a/src/Components/Blazor/Blazor/src/Hosting/RootComponentMappingCollection.cs b/src/Components/Blazor/Blazor/src/Hosting/RootComponentMappingCollection.cs new file mode 100644 index 000000000000..0e488f0deb85 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Hosting/RootComponentMappingCollection.cs @@ -0,0 +1,68 @@ +// 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.Collections.ObjectModel; +using Microsoft.AspNetCore.Components; + +namespace Microsoft.AspNetCore.Blazor.Hosting +{ + /// <summary> + /// Defines a collection of <see cref="RootComponentMapping"/> items. + /// </summary> + public class RootComponentMappingCollection : Collection<RootComponentMapping> + { + /// <summary> + /// Adds a component mapping to the collection. + /// </summary> + /// <typeparam name="TComponent">The component type.</typeparam> + /// <param name="selector">The DOM element selector.</param> + public void Add<TComponent>(string selector) where TComponent : IComponent + { + if (selector is null) + { + throw new ArgumentNullException(nameof(selector)); + } + + Add(new RootComponentMapping(typeof(TComponent), selector)); + } + + /// <summary> + /// Adds a component mapping to the collection. + /// </summary> + /// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param> + /// <param name="selector">The DOM element selector.</param> + public void Add(Type componentType, string selector) + { + if (componentType is null) + { + throw new ArgumentNullException(nameof(componentType)); + } + + if (selector is null) + { + throw new ArgumentNullException(nameof(selector)); + } + + Add(new RootComponentMapping(componentType, selector)); + } + + /// <summary> + /// Adds a collection of items to this collection. + /// </summary> + /// <param name="items">The items to add.</param> + public void AddRange(IEnumerable<RootComponentMapping> items) + { + if (items is null) + { + throw new ArgumentNullException(nameof(items)); + } + + foreach (var item in items) + { + Add(item); + } + } + } +} diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyBlazorApplicationBuilder.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyBlazorApplicationBuilder.cs deleted file mode 100644 index 8cb5d8756100..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyBlazorApplicationBuilder.cs +++ /dev/null @@ -1,54 +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.Threading.Tasks; -using Microsoft.AspNetCore.Blazor.Rendering; -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - internal class WebAssemblyBlazorApplicationBuilder : IComponentsApplicationBuilder - { - public WebAssemblyBlazorApplicationBuilder(IServiceProvider services) - { - Entries = new List<(Type componentType, string domElementSelector)>(); - Services = services; - } - - public List<(Type componentType, string domElementSelector)> Entries { get; } - - public IServiceProvider Services { get; } - - public void AddComponent(Type componentType, string domElementSelector) - { - if (componentType == null) - { - throw new ArgumentNullException(nameof(componentType)); - } - - if (domElementSelector == null) - { - throw new ArgumentNullException(nameof(domElementSelector)); - } - - Entries.Add((componentType, domElementSelector)); - } - - public async Task<WebAssemblyRenderer> CreateRendererAsync() - { - var loggerFactory = (ILoggerFactory)Services.GetService(typeof(ILoggerFactory)); - var renderer = new WebAssemblyRenderer(Services, loggerFactory); - for (var i = 0; i < Entries.Count; i++) - { - var (componentType, domElementSelector) = Entries[i]; - await renderer.AddComponentAsync(componentType, domElementSelector); - } - - return renderer; - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs index b90878fdde36..02c2693ff7ec 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHost.cs @@ -5,94 +5,135 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Rendering; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.JSInterop; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Blazor.Hosting { - internal class WebAssemblyHost : IWebAssemblyHost + /// <summary> + /// A host object for Blazor running under WebAssembly. Use <see cref="WebAssemblyHostBuilder"/> + /// to initialize a <see cref="WebAssemblyHost"/>. + /// </summary> + public sealed class WebAssemblyHost : IAsyncDisposable { - private readonly IJSRuntime _runtime; - - private IServiceScope _scope; + private readonly IServiceScope _scope; + private readonly IServiceProvider _services; + private readonly IConfiguration _configuration; + private readonly RootComponentMapping[] _rootComponents; + + // NOTE: the host is disposable because it OWNs references to disposable things. + // + // The twist is that in general dispose is not going to run even if the user puts it in a using. + // When a user refreshes or navigates away that terminates the app, like a process.exit. So the + // dispose functionality here is basically so that it can be used in unit tests. + // + // Based on the APIs that exist in Blazor today it's not possible for the + // app to get disposed, however if we add something like that in the future, most of the work is + // already done. + private bool _disposed; + private bool _started; private WebAssemblyRenderer _renderer; - public WebAssemblyHost(IServiceProvider services, IJSRuntime runtime) + internal WebAssemblyHost(IServiceProvider services, IServiceScope scope, IConfiguration configuration, RootComponentMapping[] rootComponents) { // To ensure JS-invoked methods don't get linked out, have a reference to their enclosing types GC.KeepAlive(typeof(EntrypointInvoker)); GC.KeepAlive(typeof(JSInteropMethods)); GC.KeepAlive(typeof(WebAssemblyEventDispatcher)); - Services = services ?? throw new ArgumentNullException(nameof(services)); - _runtime = runtime ?? throw new ArgumentNullException(nameof(runtime)); - } - - public IServiceProvider Services { get; } - - public Task StartAsync(CancellationToken cancellationToken = default) - { - return StartAsyncAwaited(); + _services = services; + _scope = scope; + _configuration = configuration; + _rootComponents = rootComponents; } - private async Task StartAsyncAwaited() + /// <summary> + /// Gets the application configuration. + /// </summary> + public IConfiguration Configuration => _configuration; + + /// <summary> + /// Gets the service provider associated with the application. + /// </summary> + public IServiceProvider Services => _scope.ServiceProvider; + + /// <summary> + /// Disposes the host asynchronously. + /// </summary> + /// <returns>A <see cref="ValueTask"/> which respresents the completion of disposal.</returns> + public async ValueTask DisposeAsync() { - var scopeFactory = Services.GetRequiredService<IServiceScopeFactory>(); - _scope = scopeFactory.CreateScope(); - - try + if (_disposed) { - var startup = _scope.ServiceProvider.GetService<IBlazorStartup>(); - if (startup == null) - { - var message = - $"Could not find a registered Blazor Startup class. " + - $"Using {nameof(IWebAssemblyHost)} requires a call to {nameof(IWebAssemblyHostBuilder)}.UseBlazorStartup."; - throw new InvalidOperationException(message); - } + return; + } + + _disposed = true; - // Note that we differ from the WebHost startup path here by using a 'scope' for the app builder - // as well as the Configure method. - var builder = new WebAssemblyBlazorApplicationBuilder(_scope.ServiceProvider); - startup.Configure(builder, _scope.ServiceProvider); + _renderer?.Dispose(); - _renderer = await builder.CreateRendererAsync(); + if (_scope is IAsyncDisposable asyncDisposableScope) + { + await asyncDisposableScope.DisposeAsync(); } - catch + else { - _scope.Dispose(); - _scope = null; - - if (_renderer != null) - { - _renderer.Dispose(); - _renderer = null; - } + _scope?.Dispose(); + } - throw; + if (_services is IAsyncDisposable asyncDisposableServices) + { + await asyncDisposableServices.DisposeAsync(); + } + else if (_services is IDisposable disposableServices) + { + disposableServices.Dispose(); } } - public Task StopAsync(CancellationToken cancellationToken = default) + /// <summary> + /// Runs the application associated with this host. + /// </summary> + /// <returns>A <see cref="Task"/> which represents exit of the application.</returns> + /// <remarks> + /// At this time, it's not possible to shut down a Blazor WebAssembly application using imperative code. + /// The application only stops when the hosting page is reloaded or navigated to another page. As a result + /// the task returned from this method does not complete. This method is not suitable for use in unit-testing. + /// </remarks> + public Task RunAsync() { - if (_scope != null) + // RunAsyncCore will await until the CancellationToken fires. However, we don't fire it + // currently, so the app will "run" forever. + return RunAsyncCore(CancellationToken.None); + } + + // Internal for testing. + internal async Task RunAsyncCore(CancellationToken cancellationToken) + { + if (_started) { - _scope.Dispose(); - _scope = null; + throw new InvalidOperationException("The host has already started."); } - if (_renderer != null) + _started = true; + + var tcs = new TaskCompletionSource<object>(); + + using (cancellationToken.Register(() => { tcs.TrySetResult(null); })) { - _renderer.Dispose(); - _renderer = null; - } + var loggerFactory = Services.GetRequiredService<ILoggerFactory>(); + _renderer = new WebAssemblyRenderer(Services, loggerFactory); - return Task.CompletedTask; - } + var rootComponents = _rootComponents; + for (var i = 0; i < rootComponents.Length; i++) + { + var rootComponent = rootComponents[i]; + await _renderer.AddComponentAsync(rootComponent.ComponentType, rootComponent.Selector); + } - public void Dispose() - { - (Services as IDisposable)?.Dispose(); + await tcs.Task; + } } } } diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs index 7fa4dd0ae1ca..1d1f05dce7c2 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Blazor.Services; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Routing; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; @@ -14,87 +16,89 @@ namespace Microsoft.AspNetCore.Blazor.Hosting { - // - // This code was taken virtually as-is from the Microsoft.Extensions.Hosting project in aspnet/Hosting and then - // lots of things were removed. - // - internal class WebAssemblyHostBuilder : IWebAssemblyHostBuilder + /// <summary> + /// A builder for configuring and creating a <see cref="WebAssemblyHost"/>. + /// </summary> + public sealed class WebAssemblyHostBuilder { - private List<Action<WebAssemblyHostBuilderContext, IServiceCollection>> _configureServicesActions = new List<Action<WebAssemblyHostBuilderContext, IServiceCollection>>(); - private bool _hostBuilt; - private WebAssemblyHostBuilderContext _BrowserHostBuilderContext; - private IWebAssemblyServiceFactoryAdapter _serviceProviderFactory = new WebAssemblyServiceFactoryAdapter<IServiceCollection>(new DefaultServiceProviderFactory()); - private IServiceProvider _appServices; - /// <summary> - /// A central location for sharing state between components during the host building process. + /// Creates an instance of <see cref="WebAssemblyHostBuilder"/> using the most common + /// conventions and settings. /// </summary> - public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>(); + /// <param name="args">The argument passed to the application's main method.</param> + /// <returns>A <see cref="WebAssemblyHostBuilder"/>.</returns> + public static WebAssemblyHostBuilder CreateDefault(string[] args = default) + { + // We don't use the args for anything right now, but we want to accept them + // here so that it shows up this way in the project templates. + args ??= Array.Empty<string>(); + var builder = new WebAssemblyHostBuilder(); + + // Right now we don't have conventions or behaviors that are specific to this method + // however, making this the default for the template allows us to add things like that + // in the future, while giving `new WebAssemblyHostBuilder` as an opt-out of opinionated + // settings. + return builder; + } /// <summary> - /// Adds services to the container. This can be called multiple times and the results will be additive. + /// Creates an instance of <see cref="WebAssemblyHostBuilder"/> with the minimal configuration. /// </summary> - /// <param name="configureDelegate"></param> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - public IWebAssemblyHostBuilder ConfigureServices(Action<WebAssemblyHostBuilderContext, IServiceCollection> configureDelegate) + private WebAssemblyHostBuilder() { - _configureServicesActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); - return this; + // Private right now because we don't have much reason to expose it. This can be exposed + // in the future if we want to give people a choice between CreateDefault and something + // less opinionated. + Configuration = new ConfigurationBuilder(); + RootComponents = new RootComponentMappingCollection(); + Services = new ServiceCollection(); + + InitializeDefaultServices(); } /// <summary> - /// Overrides the factory used to create the service provider. + /// Gets an <see cref="IConfigurationBuilder"/> that can be used to customize the application's + /// configuration sources. /// </summary> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - public IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory) - { - _serviceProviderFactory = new WebAssemblyServiceFactoryAdapter<TContainerBuilder>(factory ?? throw new ArgumentNullException(nameof(factory))); - return this; - } + public IConfigurationBuilder Configuration { get; } /// <summary> - /// Overrides the factory used to create the service provider. + /// Gets the collection of root component mappings configured for the application. /// </summary> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - public IWebAssemblyHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<WebAssemblyHostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory) - { - _serviceProviderFactory = new WebAssemblyServiceFactoryAdapter<TContainerBuilder>(() => _BrowserHostBuilderContext, factory ?? throw new ArgumentNullException(nameof(factory))); - return this; - } + public RootComponentMappingCollection RootComponents { get; } /// <summary> - /// Run the given actions to initialize the host. This can only be called once. + /// Gets the service collection. /// </summary> - /// <returns>An initialized <see cref="IWebAssemblyHost"/></returns> - public IWebAssemblyHost Build() - { - if (_hostBuilt) - { - throw new InvalidOperationException("Build can only be called once."); - } - _hostBuilt = true; + public IServiceCollection Services { get; } - CreateBrowserHostBuilderContext(); - CreateServiceProvider(); + /// <summary> + /// Builds a <see cref="WebAssemblyHost"/> instance based on the configuration of this builder. + /// </summary> + /// <returns>A <see cref="WebAssemblyHost"/> object.</returns> + public WebAssemblyHost Build() + { + // Intentionally overwrite configuration with the one we're creating. + var configuration = Configuration.Build(); + Services.AddSingleton<IConfiguration>(configuration); - return _appServices.GetRequiredService<IWebAssemblyHost>(); - } + // A Blazor application always runs in a scope. Since we want to make it possible for the user + // to configure services inside *that scope* inside their startup code, we create *both* the + // service provider and the scope here. + var services = Services.BuildServiceProvider(); + var scope = services.GetRequiredService<IServiceScopeFactory>().CreateScope(); - private void CreateBrowserHostBuilderContext() - { - _BrowserHostBuilderContext = new WebAssemblyHostBuilderContext(Properties); + return new WebAssemblyHost(services, scope, configuration, RootComponents.ToArray()); } - private void CreateServiceProvider() + private void InitializeDefaultServices() { - var services = new ServiceCollection(); - services.AddSingleton(_BrowserHostBuilderContext); - services.AddSingleton<IWebAssemblyHost, WebAssemblyHost>(); - services.AddSingleton<IJSRuntime>(WebAssemblyJSRuntime.Instance); - services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance); - services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance); - services.AddSingleton<ILoggerFactory, WebAssemblyLoggerFactory>(); - services.AddSingleton<HttpClient>(s => + Services.AddSingleton<IJSRuntime>(WebAssemblyJSRuntime.Instance); + Services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance); + Services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance); + Services.AddSingleton<ILoggerFactory, WebAssemblyLoggerFactory>(); + Services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(WebAssemblyConsoleLogger<>))); + Services.AddSingleton<HttpClient>(s => { // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it. var navigationManager = s.GetRequiredService<NavigationManager>(); @@ -103,20 +107,6 @@ private void CreateServiceProvider() BaseAddress = new Uri(navigationManager.BaseUri) }; }); - - // Needed for authorization - // However, since authorization isn't on by default, we could consider removing these and - // having a separate services.AddBlazorAuthorization() call that brings in the required services. - services.AddOptions(); - services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(WebAssemblyConsoleLogger<>))); - - foreach (var configureServicesAction in _configureServicesActions) - { - configureServicesAction(_BrowserHostBuilderContext, services); - } - - var builder = _serviceProviderFactory.CreateBuilder(services); - _appServices = _serviceProviderFactory.CreateServiceProvider(builder); } } } diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderContext.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderContext.cs deleted file mode 100644 index c7b7dd6f1989..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderContext.cs +++ /dev/null @@ -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.Collections.Generic; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - /// <summary> - /// Context containing the common services on the <see cref="IWebAssemblyHost" />. Some properties may be null until set by the <see cref="IWebAssemblyHost" />. - /// </summary> - public sealed class WebAssemblyHostBuilderContext - { - /// <summary> - /// Creates a new <see cref="WebAssemblyHostBuilderContext" />. - /// </summary> - /// <param name="properties">The property collection.</param> - public WebAssemblyHostBuilderContext(IDictionary<object, object> properties) - { - Properties = properties ?? throw new System.ArgumentNullException(nameof(properties)); - } - - /// <summary> - /// A central location for sharing state between components during the host building process. - /// </summary> - public IDictionary<object, object> Properties { get; } - } -} \ No newline at end of file diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderExtensions.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderExtensions.cs deleted file mode 100644 index 9b03c097665a..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilderExtensions.cs +++ /dev/null @@ -1,73 +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 Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - /// <summary> - /// Provides Blazor-specific support for <see cref="IWebAssemblyHost"/>. - /// </summary> - public static class WebAssemblyHostBuilderExtensions - { - private const string BlazorStartupKey = "Blazor.Startup"; - - /// <summary> - /// Adds services to the container. This can be called multiple times and the results will be additive. - /// </summary> - /// <param name="hostBuilder">The <see cref="IWebAssemblyHostBuilder" /> to configure.</param> - /// <param name="configureDelegate"></param> - /// <returns>The same instance of the <see cref="IWebAssemblyHostBuilder"/> for chaining.</returns> - public static IWebAssemblyHostBuilder ConfigureServices(this IWebAssemblyHostBuilder hostBuilder, Action<IServiceCollection> configureDelegate) - { - return hostBuilder.ConfigureServices((context, collection) => configureDelegate(collection)); - } - - /// <summary> - /// Configures the <see cref="IWebAssemblyHostBuilder"/> to use the provided startup class. - /// </summary> - /// <param name="builder">The <see cref="IWebAssemblyHostBuilder"/>.</param> - /// <param name="startupType">A type that configures a Blazor application.</param> - /// <returns>The <see cref="IWebAssemblyHostBuilder"/>.</returns> - public static IWebAssemblyHostBuilder UseBlazorStartup(this IWebAssemblyHostBuilder builder, Type startupType) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (builder.Properties.ContainsKey(BlazorStartupKey)) - { - throw new InvalidOperationException("A startup class has already been registered."); - } - - // It would complicate the implementation to allow multiple startup classes, and we don't - // really have a need for it. - builder.Properties.Add(BlazorStartupKey, bool.TrueString); - - var startup = new ConventionBasedStartup(Activator.CreateInstance(startupType)); - - builder.ConfigureServices(startup.ConfigureServices); - builder.ConfigureServices(s => s.AddSingleton<IBlazorStartup>(startup)); - - return builder; - } - - /// <summary> - /// Configures the <see cref="IWebAssemblyHostBuilder"/> to use the provided startup class. - /// </summary> - /// <typeparam name="TStartup">A type that configures a Blazor application.</typeparam> - /// <param name="builder">The <see cref="IWebAssemblyHostBuilder"/>.</param> - /// <returns>The <see cref="IWebAssemblyHostBuilder"/>.</returns> - public static IWebAssemblyHostBuilder UseBlazorStartup<TStartup>(this IWebAssemblyHostBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - return UseBlazorStartup(builder, typeof(TStartup)); - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostExtensions.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostExtensions.cs deleted file mode 100644 index d08162a590ec..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostExtensions.cs +++ /dev/null @@ -1,36 +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; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - /// <summary> - /// Extension methods for <see cref="IWebAssemblyHost"/>. - /// </summary> - public static class WebAssemblyHostExtensions - { - /// <summary> - /// Runs the application. - /// </summary> - /// <param name="host">The <see cref="IWebAssemblyHost"/> to run.</param> - /// <remarks> - /// Currently, Blazor applications running in the browser don't have a lifecycle - the application does not - /// get a chance to gracefully shut down. For now, <see cref="Run(IWebAssemblyHost)"/> simply starts the host - /// and allows execution to continue. - /// </remarks> - public static void Run(this IWebAssemblyHost host) - { - // Behave like async void, because we don't yet support async-main properly on WebAssembly. - // However, don't actualy make this method async, because we rely on startup being synchronous - // for things like attaching navigation event handlers. - host.StartAsync().ContinueWith(task => - { - if (task.Exception != null) - { - Console.WriteLine(task.Exception); - } - }); - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyServiceFactoryAdapter.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyServiceFactoryAdapter.cs deleted file mode 100644 index fcc879653abb..000000000000 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyServiceFactoryAdapter.cs +++ /dev/null @@ -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 Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Blazor.Hosting -{ - // Equivalent to https://github.com/aspnet/Extensions/blob/master/src/Hosting/Hosting/src/Internal/ServiceFactoryAdapter.cs - - internal class WebAssemblyServiceFactoryAdapter<TContainerBuilder> : IWebAssemblyServiceFactoryAdapter - { - private IServiceProviderFactory<TContainerBuilder> _serviceProviderFactory; - private readonly Func<WebAssemblyHostBuilderContext> _contextResolver; - private Func<WebAssemblyHostBuilderContext, IServiceProviderFactory<TContainerBuilder>> _factoryResolver; - - public WebAssemblyServiceFactoryAdapter(IServiceProviderFactory<TContainerBuilder> serviceProviderFactory) - { - _serviceProviderFactory = serviceProviderFactory ?? throw new ArgumentNullException(nameof(serviceProviderFactory)); - } - - public WebAssemblyServiceFactoryAdapter(Func<WebAssemblyHostBuilderContext> contextResolver, Func<WebAssemblyHostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factoryResolver) - { - _contextResolver = contextResolver ?? throw new ArgumentNullException(nameof(contextResolver)); - _factoryResolver = factoryResolver ?? throw new ArgumentNullException(nameof(factoryResolver)); - } - - public object CreateBuilder(IServiceCollection services) - { - if (_serviceProviderFactory == null) - { - _serviceProviderFactory = _factoryResolver(_contextResolver()); - - if (_serviceProviderFactory == null) - { - throw new InvalidOperationException("The resolver returned a null IServiceProviderFactory"); - } - } - return _serviceProviderFactory.CreateBuilder(services); - } - - public IServiceProvider CreateServiceProvider(object containerBuilder) - { - if (_serviceProviderFactory == null) - { - throw new InvalidOperationException("CreateBuilder must be called before CreateServiceProvider"); - } - - return _serviceProviderFactory.CreateServiceProvider((TContainerBuilder)containerBuilder); - } - } -} diff --git a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj index be94e420a214..ff30d9d9c83d 100644 --- a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> @@ -9,7 +9,7 @@ <ItemGroup> <Reference Include="Mono.WebAssembly.Interop" /> <Reference Include="Microsoft.AspNetCore.Components.Web" /> - <Reference Include="Microsoft.Extensions.Options" /> + <Reference Include="Microsoft.Extensions.Configuration" /> </ItemGroup> <ItemGroup> diff --git a/src/Components/Blazor/Blazor/test/Hosting/ConventionBasedStartupTest.cs b/src/Components/Blazor/Blazor/test/Hosting/ConventionBasedStartupTest.cs deleted file mode 100644 index cbc73b79f832..000000000000 --- a/src/Components/Blazor/Blazor/test/Hosting/ConventionBasedStartupTest.cs +++ /dev/null @@ -1,210 +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 Microsoft.AspNetCore.Blazor.Hosting; -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Hosting -{ - public class ConventionBasedStartupTest - { - [Fact] - public void ConventionBasedStartup_GetConfigureServicesMethod_FindsConfigureServices() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup1()); - - // Act - var method = startup.GetConfigureServicesMethod(); - - // Assert - Assert.Equal(typeof(IServiceCollection), method.GetParameters()[0].ParameterType); - } - - private class MyStartup1 - { - public void ConfigureServices(IServiceCollection services) - { - } - - // Ignored - public void ConfigureServices(DateTime x) - { - - } - - // Ignored - private void ConfigureServices(int x) - { - } - - // Ignored - public static void ConfigureServices(string x) - { - } - } - - [Fact] - public void ConventionBasedStartup_GetConfigureServicesMethod_NoMethodFound() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup2()); - - // Act - var method = startup.GetConfigureServicesMethod(); - - // Assert - Assert.Null(method); - } - - private class MyStartup2 - { - } - - [Fact] - public void ConventionBasedStartup_ConfigureServices_CallsMethod() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup3()); - var services = new ServiceCollection(); - - // Act - startup.ConfigureServices(services); - - // Assert - Assert.NotEmpty(services); - } - - private class MyStartup3 - { - public void ConfigureServices(IServiceCollection services) - { - services.AddSingleton("foo"); - } - } - - [Fact] - public void ConventionBasedStartup_ConfigureServices_NoMethodFound() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup4()); - var services = new ServiceCollection(); - - // Act - startup.ConfigureServices(services); - - // Assert - Assert.Empty(services); - } - - private class MyStartup4 - { - } - - [Fact] - public void ConventionBasedStartup_GetConfigureMethod_FindsConfigure() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup5()); - - // Act - var method = startup.GetConfigureMethod(); - - // Assert - Assert.Empty(method.GetParameters()); - } - - private class MyStartup5 - { - public void Configure() - { - } - - // Ignored - private void Configure(int x) - { - } - - // Ignored - public static void Configure(string x) - { - } - } - - [Fact] - public void ConventionBasedStartup_GetConfigureMethod_NoMethodFoundThrows() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup6()); - - // Act - var ex = Assert.Throws<InvalidOperationException>(() => startup.GetConfigureMethod()); - - // Assert - Assert.Equal("The startup class must define a 'Configure' method.", ex.Message); - } - - private class MyStartup6 - { - } - - [Fact] - public void ConventionBasedStartup_GetConfigureMethod_OverloadedThrows() - { - // Arrange - var startup = new ConventionBasedStartup(new MyStartup7()); - - // Act - var ex = Assert.Throws<InvalidOperationException>(() => startup.GetConfigureMethod()); - - // Assert - Assert.Equal("Overloading the 'Configure' method is not supported.", ex.Message); - } - - private class MyStartup7 - { - public void Configure() - { - } - - public void Configure(string x) - { - } - } - - [Fact] - public void ConventionBasedStartup_Configure() - { - // Arrange - var instance = new MyStartup8(); - var startup = new ConventionBasedStartup(instance); - - var services = new ServiceCollection().AddSingleton("foo").BuildServiceProvider(); - var builder = new WebAssemblyBlazorApplicationBuilder(services); - - // Act - startup.Configure(builder, services); - - // Assert - Assert.Collection( - instance.Arguments, - a => Assert.Same(builder, a), - a => Assert.Equal("foo", a)); - } - - private class MyStartup8 - { - public List<object> Arguments { get; } = new List<object>(); - - public void Configure(IComponentsApplicationBuilder app, string foo) - { - Arguments.Add(app); - Arguments.Add(foo); - } - } - } -} diff --git a/src/Components/Blazor/Blazor/test/Hosting/RootComponentMappingTest.cs b/src/Components/Blazor/Blazor/test/Hosting/RootComponentMappingTest.cs new file mode 100644 index 000000000000..724940288071 --- /dev/null +++ b/src/Components/Blazor/Blazor/test/Hosting/RootComponentMappingTest.cs @@ -0,0 +1,37 @@ +// 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.Text; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Hosting +{ + public class RootComponentMappingTest + { + [Fact] + public void Constructor_ValidatesComponentType_Success() + { + // Arrange + // Act + var mapping = new RootComponentMapping(typeof(Router), "test"); + + // Assert (does not throw) + GC.KeepAlive(mapping); + } + + [Fact] + public void Constructor_ValidatesComponentType_Failure() + { + // Arrange + // Act & Assert + ExceptionAssert.ThrowsArgument( + () => new RootComponentMapping(typeof(StringBuilder), "test"), + "componentType", + $"The type '{nameof(StringBuilder)}' must implement IComponent to be used as a root component."); + } + } +} diff --git a/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostBuilderTest.cs b/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostBuilderTest.cs index 4acf6f99a30e..77b6583d260e 100644 --- a/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostBuilderTest.cs +++ b/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostBuilderTest.cs @@ -3,160 +3,100 @@ using System; using System.Collections.Generic; +using System.Net.Http; using System.Text; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.JSInterop; using Xunit; -namespace Microsoft.AspNetCore.Blazor.Hosting.Test +namespace Microsoft.AspNetCore.Blazor.Hosting { public class WebAssemblyHostBuilderTest { [Fact] - public void HostBuilder_CanCallBuild_BuildsServices() + public void Build_AllowsConfiguringConfiguration() { // Arrange - var builder = new WebAssemblyHostBuilder(); + var builder = WebAssemblyHostBuilder.CreateDefault(); - // Act - var host = builder.Build(); - - // Assert - Assert.NotNull(host.Services.GetService(typeof(IWebAssemblyHost))); - } - - [Fact] - public void HostBuilder_CanConfigureAdditionalServices() - { - // Arrange - var builder = new WebAssemblyHostBuilder(); - builder.ConfigureServices((c, s) => s.AddSingleton<string>("foo")); - builder.ConfigureServices((c, s) => s.AddSingleton<StringBuilder>(new StringBuilder("bar"))); + builder.Configuration.AddInMemoryCollection(new[] + { + new KeyValuePair<string, string>("key", "value"), + }); // Act var host = builder.Build(); // Assert - Assert.Equal("foo", host.Services.GetService(typeof(string))); - Assert.Equal("bar", host.Services.GetService(typeof(StringBuilder)).ToString()); + Assert.Equal("value", host.Configuration["key"]); } - [Fact] - public void HostBuilder_UseBlazorStartup_CanConfigureAdditionalServices() + [Fact] + public void Build_AllowsConfiguringServices() { // Arrange - var builder = new WebAssemblyHostBuilder(); - builder.UseBlazorStartup<MyStartup>(); - builder.ConfigureServices((c, s) => s.AddSingleton<StringBuilder>(new StringBuilder("bar"))); + var builder = WebAssemblyHostBuilder.CreateDefault(); - // Act - var host = builder.Build(); - - // Assert - Assert.Equal("foo", host.Services.GetService(typeof(string))); - Assert.Equal("bar", host.Services.GetService(typeof(StringBuilder)).ToString()); - } - - [Fact] - public void HostBuilder_UseBlazorStartup_DoesNotAllowMultiple() - { - // Arrange - var builder = new WebAssemblyHostBuilder(); - builder.UseBlazorStartup<MyStartup>(); - - // Act - var ex = Assert.Throws<InvalidOperationException>(() => builder.UseBlazorStartup<MyStartup>()); - - // Assert - Assert.Equal("A startup class has already been registered.", ex.Message); - } - - private class MyStartup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddSingleton<string>("foo"); - } - } - - [Fact] - public void HostBuilder_CanCustomizeServiceFactory() - { - // Arrange - var builder = new WebAssemblyHostBuilder(); - builder.UseServiceProviderFactory(new TestServiceProviderFactory()); + // This test also verifies that we create a scope. + builder.Services.AddScoped<StringBuilder>(); // Act var host = builder.Build(); // Assert - Assert.IsType<TestServiceProvider>(host.Services); + Assert.NotNull(host.Services.GetRequiredService<StringBuilder>()); } [Fact] - public void HostBuilder_CanCustomizeServiceFactoryWithContext() + public void Build_AddsConfigurationToServices() { // Arrange - var builder = new WebAssemblyHostBuilder(); - builder.UseServiceProviderFactory(context => + var builder = WebAssemblyHostBuilder.CreateDefault(); + + builder.Configuration.AddInMemoryCollection(new[] { - Assert.NotNull(context.Properties); - Assert.Same(builder.Properties, context.Properties); - return new TestServiceProviderFactory(); + new KeyValuePair<string, string>("key", "value"), }); // Act var host = builder.Build(); // Assert - Assert.IsType<TestServiceProvider>(host.Services); + var configuration = host.Services.GetRequiredService<IConfiguration>(); + Assert.Equal("value", configuration["key"]); } - private class TestServiceProvider : IServiceProvider + private static IReadOnlyList<Type> DefaultServiceTypes { - private readonly IServiceProvider _underlyingProvider; - - public TestServiceProvider(IServiceProvider underlyingProvider) + get { - _underlyingProvider = underlyingProvider; - } - - public object GetService(Type serviceType) - { - if (serviceType == typeof(IWebAssemblyHost)) + return new Type[] { - // Since the test will make assertions about the resulting IWebAssemblyHost, - // show that custom DI containers have the power to substitute themselves - // as the IServiceProvider - return new WebAssemblyHost( - this, _underlyingProvider.GetRequiredService<IJSRuntime>()); - } - else - { - return _underlyingProvider.GetService(serviceType); - } + typeof(IJSRuntime), + typeof(NavigationManager), + typeof(INavigationInterception), + typeof(ILoggerFactory), + typeof(HttpClient), + typeof(ILogger<>), + }; } } - private class TestServiceProviderFactory : IServiceProviderFactory<IServiceCollection> + [Fact] + public void Constructor_AddsDefaultServices() { - public IServiceCollection CreateBuilder(IServiceCollection services) - { - return new TestServiceCollection(services); - } - - public IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection) - { - Assert.IsType<TestServiceCollection>(serviceCollection); - return new TestServiceProvider(serviceCollection.BuildServiceProvider()); - } + // Arrange & Act + var builder = WebAssemblyHostBuilder.CreateDefault(); - class TestServiceCollection : List<ServiceDescriptor>, IServiceCollection + // Assert + Assert.Equal(DefaultServiceTypes.Count, builder.Services.Count); + foreach (var type in DefaultServiceTypes) { - public TestServiceCollection(IEnumerable<ServiceDescriptor> collection) - : base(collection) - { - } + Assert.Single(builder.Services, d => d.ServiceType == type); } } } diff --git a/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostTest.cs b/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostTest.cs index f99245e317d5..b83833456608 100644 --- a/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostTest.cs +++ b/src/Components/Blazor/Blazor/test/Hosting/WebAssemblyHostTest.cs @@ -2,64 +2,89 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.AspNetCore.Components.Hosting; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.JSInterop; -using Mono.WebAssembly.Interop; using Xunit; -namespace Microsoft.AspNetCore.Blazor.Hosting.Test +namespace Microsoft.AspNetCore.Blazor.Hosting { public class WebAssemblyHostTest { - [Fact] - public async Task BrowserHost_StartAsync_ThrowsWithoutStartup() + // This won't happen in the product code, but we need to be able to safely call RunAsync + // to be able to test a few of the other details. + [Fact] + public async Task RunAsync_CanExitBasedOnCancellationToken() { // Arrange - var builder = new WebAssemblyHostBuilder(); + var builder = WebAssemblyHostBuilder.CreateDefault(); var host = builder.Build(); + var cts = new CancellationTokenSource(); + // Act - var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await host.StartAsync()); + var task = host.RunAsyncCore(cts.Token); - // Assert - Assert.Equal( - "Could not find a registered Blazor Startup class. " + - "Using IWebAssemblyHost requires a call to IWebAssemblyHostBuilder.UseBlazorStartup.", - ex.Message); + cts.Cancel(); + await task.TimeoutAfter(TimeSpan.FromSeconds(3)); + + // Assert (does not throw) } [Fact] - public async Task BrowserHost_StartAsync_RunsConfigureMethod() + public async Task RunAsync_CallingTwiceCausesException() { // Arrange - var builder = new WebAssemblyHostBuilder(); - - var startup = new MockStartup(); - builder.ConfigureServices((c, s) => { s.AddSingleton<IBlazorStartup>(startup); }); - + var builder = WebAssemblyHostBuilder.CreateDefault(); var host = builder.Build(); + var cts = new CancellationTokenSource(); + var task = host.RunAsyncCore(cts.Token); + // Act - await host.StartAsync(); + var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => host.RunAsyncCore(cts.Token)); + + cts.Cancel(); + await task.TimeoutAfter(TimeSpan.FromSeconds(3)); // Assert - Assert.True(startup.ConfigureCalled); + Assert.Equal("The host has already started.", ex.Message); } - private class MockStartup : IBlazorStartup + [Fact] + public async Task DisposeAsync_CanDisposeAfterCallingRunAsync() { - public bool ConfigureCalled { get; set; } + // Arrange + var builder = WebAssemblyHostBuilder.CreateDefault(); + builder.Services.AddSingleton<DisposableService>(); + var host = builder.Build(); + + var disposable = host.Services.GetRequiredService<DisposableService>(); + + var cts = new CancellationTokenSource(); - public void Configure(IComponentsApplicationBuilder app, IServiceProvider services) + // Act + await using (host) { - ConfigureCalled = true; + var task = host.RunAsyncCore(cts.Token); + + cts.Cancel(); + await task.TimeoutAfter(TimeSpan.FromSeconds(3)); } - public void ConfigureServices(IServiceCollection services) + // Assert + Assert.Equal(1, disposable.DisposeCount); + } + + private class DisposableService : IAsyncDisposable + { + public int DisposeCount { get; private set; } + + public ValueTask DisposeAsync() { + DisposeCount++; + return new ValueTask(Task.CompletedTask); } } } diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Client/Program.cs b/src/Components/Blazor/testassets/HostedInAspNet.Client/Program.cs index 69ee439533d0..e922c2996f75 100644 --- a/src/Components/Blazor/testassets/HostedInAspNet.Client/Program.cs +++ b/src/Components/Blazor/testassets/HostedInAspNet.Client/Program.cs @@ -1,19 +1,19 @@ // 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.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Hosting; namespace HostedInAspNet.Client { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - CreateHostBuilder(args).Build().Run(); - } + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add<Home>("app"); - public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => - BlazorWebAssemblyHost.CreateDefaultBuilder() - .UseBlazorStartup<Startup>(); + await builder.Build().RunAsync(); + } } } diff --git a/src/Components/Blazor/testassets/HostedInAspNet.Client/Startup.cs b/src/Components/Blazor/testassets/HostedInAspNet.Client/Startup.cs deleted file mode 100644 index a06163b9e05b..000000000000 --- a/src/Components/Blazor/testassets/HostedInAspNet.Client/Startup.cs +++ /dev/null @@ -1,20 +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.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace HostedInAspNet.Client -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IComponentsApplicationBuilder app) - { - app.AddComponent<Home>("app"); - } - } -} diff --git a/src/Components/Blazor/testassets/StandaloneApp/Program.cs b/src/Components/Blazor/testassets/StandaloneApp/Program.cs index 530de72870dc..8da14834b659 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/Program.cs +++ b/src/Components/Blazor/testassets/StandaloneApp/Program.cs @@ -1,19 +1,19 @@ // 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.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Hosting; namespace StandaloneApp { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - CreateHostBuilder(args).Build().Run(); - } + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add<App>("app"); - public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => - BlazorWebAssemblyHost.CreateDefaultBuilder() - .UseBlazorStartup<Startup>(); + await builder.Build().RunAsync(); + } } } diff --git a/src/Components/Blazor/testassets/StandaloneApp/Startup.cs b/src/Components/Blazor/testassets/StandaloneApp/Startup.cs deleted file mode 100644 index 79564e8d9d6c..000000000000 --- a/src/Components/Blazor/testassets/StandaloneApp/Startup.cs +++ /dev/null @@ -1,20 +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.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace StandaloneApp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IComponentsApplicationBuilder app) - { - app.AddComponent<App>("app"); - } - } -} diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index 0d74c8c6b7cc..6a721adf63b7 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -100,7 +100,7 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) Format = "n2", }); - var testAssembly = typeof(TestApp.Startup).Assembly; + var testAssembly = typeof(TestApp.Program).Assembly; var testAssemblyLocation = new FileInfo(testAssembly.Location); var testApp = new DirectoryInfo(Path.Combine( testAssemblyLocation.Directory.FullName, @@ -143,7 +143,7 @@ static IHost StartTestApp() var args = new[] { "--urls", "http://127.0.0.1:0", - "--applicationpath", typeof(TestApp.Startup).Assembly.Location, + "--applicationpath", typeof(TestApp.Program).Assembly.Location, }; var host = DevHostServerProgram.BuildWebHost(args); diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs index 403bc37c9c35..57a3697382f3 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Program.cs @@ -1,19 +1,19 @@ // 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.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Hosting; namespace Wasm.Performance.TestApp { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - CreateHostBuilder(args).Build().Run(); - } + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add<App>("app"); - public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => - BlazorWebAssemblyHost.CreateDefaultBuilder() - .UseBlazorStartup<Startup>(); + await builder.Build().RunAsync(); + } } } diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs deleted file mode 100644 index c79b0efb8c38..000000000000 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Startup.cs +++ /dev/null @@ -1,20 +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.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace Wasm.Performance.TestApp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IComponentsApplicationBuilder app) - { - app.AddComponent<App>("app"); - } - } -} diff --git a/src/Components/test/testassets/BasicTestApp/Program.cs b/src/Components/test/testassets/BasicTestApp/Program.cs index 2be7d81b4e2d..0c62f05bd1af 100644 --- a/src/Components/test/testassets/BasicTestApp/Program.cs +++ b/src/Components/test/testassets/BasicTestApp/Program.cs @@ -3,8 +3,13 @@ using System; using System.Globalization; +using System.Runtime.InteropServices; using System.Threading.Tasks; +using BasicTestApp.AuthTest; using Microsoft.AspNetCore.Blazor.Hosting; +using Microsoft.AspNetCore.Blazor.Http; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; using Mono.WebAssembly.Interop; namespace BasicTestApp @@ -18,12 +23,26 @@ public static async Task Main(string[] args) // We want the culture to be en-US so that the tests for bind can work consistently. CultureInfo.CurrentCulture = new CultureInfo("en-US"); - CreateHostBuilder(args).Build().Run(); - } + var builder = WebAssemblyHostBuilder.CreateDefault(args); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY"))) + { + // Needed because the test server runs on a different port than the client app, + // and we want to test sending/receiving cookies under this config + WebAssemblyHttpMessageHandlerOptions.DefaultCredentials = FetchCredentialsOption.Include; + } - public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => - BlazorWebAssemblyHost.CreateDefaultBuilder() - .UseBlazorStartup<Startup>(); + builder.RootComponents.Add<Index>("root"); + + builder.Services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>(); + builder.Services.AddAuthorizationCore(options => + { + options.AddPolicy("NameMustStartWithB", policy => + policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith("B") ?? false)); + }); + + await builder.Build().RunAsync(); + } // Supports E2E tests in StartupErrorNotificationTest private static async Task SimulateErrorsIfNeededForTest() diff --git a/src/Components/test/testassets/BasicTestApp/Startup.cs b/src/Components/test/testassets/BasicTestApp/Startup.cs deleted file mode 100644 index 008a988316c9..000000000000 --- a/src/Components/test/testassets/BasicTestApp/Startup.cs +++ /dev/null @@ -1,39 +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.InteropServices; -using BasicTestApp.AuthTest; -using Microsoft.AspNetCore.Blazor.Http; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace BasicTestApp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>(); - - services.AddAuthorizationCore(options => - { - options.AddPolicy("NameMustStartWithB", policy => - policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith("B") ?? false)); - }); - } - - public void Configure(IComponentsApplicationBuilder app) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY"))) - { - // Needed because the test server runs on a different port than the client app, - // and we want to test sending/receiving cookies underling this config - WebAssemblyHttpMessageHandlerOptions.DefaultCredentials = FetchCredentialsOption.Include; - } - - app.AddComponent<Index>("root"); - } - } -} diff --git a/src/Components/test/testassets/TestServer/CorsStartup.cs b/src/Components/test/testassets/TestServer/CorsStartup.cs index a4d91a84aa04..28dda32d903a 100644 --- a/src/Components/test/testassets/TestServer/CorsStartup.cs +++ b/src/Components/test/testassets/TestServer/CorsStartup.cs @@ -46,7 +46,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.Map("/subdir", app => { app.UseStaticFiles(); - app.UseClientSideBlazorFiles<BasicTestApp.Startup>(); + app.UseClientSideBlazorFiles<BasicTestApp.Program>(); app.UseRouting(); @@ -55,7 +55,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseEndpoints(endpoints => { endpoints.MapControllers(); - endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Startup>("index.html"); + endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Program>("index.html"); }); }); } diff --git a/src/Components/test/testassets/TestServer/InternationalizationStartup.cs b/src/Components/test/testassets/TestServer/InternationalizationStartup.cs index d508ed797b44..7521ebe34b28 100644 --- a/src/Components/test/testassets/TestServer/InternationalizationStartup.cs +++ b/src/Components/test/testassets/TestServer/InternationalizationStartup.cs @@ -37,7 +37,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.Map("/subdir", app => { app.UseStaticFiles(); - app.UseClientSideBlazorFiles<BasicTestApp.Startup>(); + app.UseClientSideBlazorFiles<BasicTestApp.Program>(); app.UseRequestLocalization(options => { diff --git a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs index 483dd00d7864..d32f48f8e3a6 100644 --- a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs +++ b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs @@ -36,7 +36,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) // The client-side files middleware needs to be here because the base href in hardcoded to /subdir/ app.Map("/subdir", app => { - app.UseClientSideBlazorFiles<BasicTestApp.Startup>(); + app.UseClientSideBlazorFiles<BasicTestApp.Program>(); }); // The calls to `Map` allow us to test each of these overloads, while keeping them isolated. @@ -46,7 +46,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseEndpoints(endpoints => { - endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Startup>("index.html"); + endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Program>("index.html"); }); }); @@ -56,7 +56,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseEndpoints(endpoints => { - endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Startup>("test/{*path:nonfile}", "index.html"); + endpoints.MapFallbackToClientSideBlazor<BasicTestApp.Program>("test/{*path:nonfile}", "index.html"); }); }); @@ -66,7 +66,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseEndpoints(endpoints => { - endpoints.MapFallbackToClientSideBlazor(typeof(BasicTestApp.Startup).Assembly.Location, "index.html"); + endpoints.MapFallbackToClientSideBlazor(typeof(BasicTestApp.Program).Assembly.Location, "index.html"); }); }); @@ -76,7 +76,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseEndpoints(endpoints => { - endpoints.MapFallbackToClientSideBlazor(typeof(BasicTestApp.Startup).Assembly.Location, "test/{*path:nonfile}", "index.html"); + endpoints.MapFallbackToClientSideBlazor(typeof(BasicTestApp.Program).Assembly.Location, "test/{*path:nonfile}", "index.html"); }); }); } diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs index 03d510452d1a..06790b9c57c6 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs @@ -1,4 +1,12 @@ -using Microsoft.AspNetCore.Blazor.Hosting; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Text; +using Microsoft.AspNetCore.Blazor.Hosting; +using Microsoft.Extensions.DependencyInjection; +#if (!NoAuth) +using Microsoft.AspNetCore.Components.Authorization; +#endif #if (Hosted) namespace BlazorWasm_CSharp.Client @@ -8,13 +16,19 @@ namespace BlazorWasm_CSharp { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - CreateHostBuilder(args).Build().Run(); - } + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add<App>("app"); - public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => - BlazorWebAssemblyHost.CreateDefaultBuilder() - .UseBlazorStartup<Startup>(); + // use builder.Services to configure application services. +#if (IndividualLocalAuth) + builder.Services.AddOptions(); + builder.Services.AddAuthorizationCore(); + builder.Services.AddSingleton<AuthenticationStateProvider, HostAuthenticationStateProvider>(); +#endif + + await builder.Build().RunAsync(); + } } } diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs deleted file mode 100644 index 38fd10a30eac..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs +++ /dev/null @@ -1,28 +0,0 @@ -#if (!NoAuth) -using Microsoft.AspNetCore.Components.Authorization; -#endif -using Microsoft.AspNetCore.Components.Builder; -using Microsoft.Extensions.DependencyInjection; - -#if (Hosted) -namespace BlazorWasm_CSharp.Client -#else -namespace BlazorWasm_CSharp -#endif -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { -#if (IndividualLocalAuth) - services.AddAuthorizationCore(); - services.AddSingleton<AuthenticationStateProvider, HostAuthenticationStateProvider>(); -#endif - } - - public void Configure(IComponentsApplicationBuilder app) - { - app.AddComponent<App>("app"); - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs index fd1767bd4744..eb96bae0e856 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs @@ -83,7 +83,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) #endif app.UseStaticFiles(); - app.UseClientSideBlazorFiles<Client.Startup>(); + app.UseClientSideBlazorFiles<Client.Program>(); app.UseRouting(); @@ -99,7 +99,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) #endif endpoints.MapControllers(); - endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html"); + endpoints.MapFallbackToClientSideBlazor<Client.Program>("index.html"); }); } } From c7e6beec3caec49231124ca59d15d6f3f57cd8c9 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Tue, 21 Jan 2020 16:38:22 -0800 Subject: [PATCH 057/322] Include compressed size in output (#18485) --- .../Wasm.Performance/Driver/Program.cs | 73 ++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index 6a721adf63b7..d3fb6f2c8a45 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Runtime.ExceptionServices; using System.Text.Encodings.Web; @@ -55,8 +56,9 @@ public static async Task<int> Main(string[] args) browser.Url = launchUrl; browser.Navigate(); - var results = await benchmarkResult.Task; - FormatAsBenchmarksOutput(results); + var appSize = GetBlazorAppSize(); + await Task.WhenAll(benchmarkResult.Task, appSize); + FormatAsBenchmarksOutput(benchmarkResult.Task.Result, appSize.Result); Console.WriteLine("Done executing benchmark"); return 0; @@ -67,7 +69,7 @@ internal static void SetBenchmarkResult(List<BenchmarkResult> result) benchmarkResult.TrySetResult(result); } - private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) + private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results, (long publishSize, long compressedSize) sizes) { // Sample of the the format: https://github.com/aspnet/Benchmarks/blob/e55f9e0312a7dd019d1268c1a547d1863f0c7237/src/Benchmarks/Program.cs#L51-L67 var output = new BenchmarkOutput(); @@ -100,17 +102,11 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) Format = "n2", }); - var testAssembly = typeof(TestApp.Program).Assembly; - var testAssemblyLocation = new FileInfo(testAssembly.Location); - var testApp = new DirectoryInfo(Path.Combine( - testAssemblyLocation.Directory.FullName, - testAssembly.GetName().Name)); - output.Measurements.Add(new BenchmarkMeasurement { Timestamp = DateTime.UtcNow, - Name = "Publish size", - Value = GetDirectorySize(testApp) / 1024, + Name = "blazorwasm/publish-size", + Value = sizes.publishSize / 1024, }); output.Metadata.Add(new BenchmarkMetadata @@ -122,15 +118,11 @@ private static void FormatAsBenchmarksOutput(List<BenchmarkResult> results) Format = "n2", }); - var gzip = new FileInfo(Path.Combine( - testAssemblyLocation.Directory.FullName, - $"{testAssembly.GetName().Name}.gzip")); - output.Measurements.Add(new BenchmarkMeasurement { Timestamp = DateTime.UtcNow, - Name = "Publish size (compressed)", - Value = (gzip.Exists ? gzip.Length : 0) / 1024, + Name = "blazorwasm/compressed-publish-size", + Value = sizes.compressedSize / 1024, }); Console.WriteLine("#StartJobStatistics"); @@ -205,6 +197,17 @@ static string GetListeningUrl(IHost testApp) .First(); } + static async Task<(long size, long compressedSize)> GetBlazorAppSize() + { + var testAssembly = typeof(TestApp.Startup).Assembly; + var testAssemblyLocation = new FileInfo(testAssembly.Location); + var testApp = new DirectoryInfo(Path.Combine( + testAssemblyLocation.Directory.FullName, + testAssembly.GetName().Name)); + + return (GetDirectorySize(testApp), await GetBrotliCompressedSize(testApp)); + } + static long GetDirectorySize(DirectoryInfo directory) { // This can happen if you run the app without publishing it. @@ -228,5 +231,41 @@ static long GetDirectorySize(DirectoryInfo directory) return size; } + + static async Task<long> GetBrotliCompressedSize(DirectoryInfo directory) + { + if (!directory.Exists) + { + return 0; + } + + var tasks = new List<Task<long>>(); + foreach (var item in directory.EnumerateFileSystemInfos()) + { + if (item is FileInfo fileInfo) + { + tasks.Add(GetCompressedFileSize(fileInfo)); + } + else if (item is DirectoryInfo directoryInfo) + { + tasks.Add(GetBrotliCompressedSize(directoryInfo)); + } + } + + return (await Task.WhenAll(tasks)).Sum(s => s); + + async Task<long> GetCompressedFileSize(FileInfo fileInfo) + { + using var inputStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1, useAsync: true); + using var outputStream = new MemoryStream(); + + using (var brotliStream = new BrotliStream(outputStream, CompressionLevel.Optimal, leaveOpen: true)) + { + await inputStream.CopyToAsync(brotliStream); + } + + return outputStream.Length; + } + } } } From ffac6870914d1f4335240500b65375bff6e3cbd4 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson <jacalvar@microsoft.com> Date: Wed, 22 Jan 2020 14:00:39 -0800 Subject: [PATCH 058/322] Revert "[Fixes #17014] Add an auth-enabled template for Blazor WASM projects (#18354)" (#18516) This reverts commit e64b8a91ad1a5acea64f7d2a51ac00618ad96876. --- eng/Versions.props | 4 - .../BlazorWasm-CSharp.Client.csproj.in | 1 - .../BlazorWasm-CSharp.Server.csproj.in | 17 -- ...crosoft.AspNetCore.Blazor.Templates.csproj | 10 +- .../.template.config/dotnetcli.host.json | 28 +- .../.template.config/template.json | 181 ------------ .../.template.config/vs-2017.3.host.json | 24 -- .../BlazorWasm-CSharp/Client/App.razor | 17 +- .../Client/Pages/FetchData.razor | 6 - .../BlazorWasm-CSharp/Client/Program.cs | 10 - .../HostAuthenticationStateProvider.cs | 56 ---- .../LoginDisplay.IndividualLocalAuth.razor | 12 - .../Client/Shared/MainLayout.Auth.razor | 16 - ...inLayout.NoAuth.razor => MainLayout.razor} | 0 .../BlazorWasm-CSharp/Client/_Imports.razor | 3 - .../Client/wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../Identity/Pages/Account/LogOut.cshtml | 15 - .../Pages/Shared/_LoginPartial.cshtml | 27 -- .../Server/Controllers/UserController.cs | 61 ---- .../Controllers/WeatherForecastController.cs | 6 - .../Server/Data/ApplicationDbContext.cs | 16 - ...000000000_CreateIdentitySchema.Designer.cs | 270 ----------------- .../00000000000000_CreateIdentitySchema.cs | 217 -------------- .../ApplicationDbContextModelSnapshot.cs | 268 ----------------- ...000000000_CreateIdentitySchema.Designer.cs | 277 ------------------ .../00000000000000_CreateIdentitySchema.cs | 220 -------------- .../ApplicationDbContextModelSnapshot.cs | 275 ----------------- .../BlazorWasm-CSharp/Server/Startup.cs | 61 +--- .../content/BlazorWasm-CSharp/Server/app.db | Bin 106496 -> 0 bytes .../Server/appsettings.Development.json | 9 - .../BlazorWasm-CSharp/Server/appsettings.json | 19 -- .../Shared/Authorization/ClaimValue.cs | 18 -- .../Shared/Authorization/UserInfo.cs | 19 -- .../test/BlazorWasmTemplateTest.cs | 107 +------ 34 files changed, 11 insertions(+), 2259 deletions(-) delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor rename src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/{MainLayout.NoAuth.razor => MainLayout.razor} (100%) delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs delete mode 100644 src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs diff --git a/eng/Versions.props b/eng/Versions.props index 5f4be96aee8b..acef5287d107 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -204,10 +204,6 @@ <SystemThreadingTasksExtensionsPackageVersion>4.5.2</SystemThreadingTasksExtensionsPackageVersion> <!-- Packages developed by @aspnet, but manually updated as necessary. --> <LibuvPackageVersion>1.10.0</LibuvPackageVersion> - <MicrosoftAspNetCoreIdentityUIPackageVersion>3.1.0</MicrosoftAspNetCoreIdentityUIPackageVersion> - <MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>3.1.0</MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion> - <MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>3.1.0</MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion> - <MicrosoftAspNetCoreComponentsAuthorizationPackageVersion>3.1.0</MicrosoftAspNetCoreComponentsAuthorizationPackageVersion> <MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion> <!-- Partner teams --> <MicrosoftAzureKeyVaultPackageVersion>2.3.2</MicrosoftAzureKeyVaultPackageVersion> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in index 3ef13b2f3344..70927b08e331 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in @@ -10,7 +10,6 @@ <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="${MicrosoftAspNetCoreBlazorBuildPackageVersion}" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="${MicrosoftAspNetCoreBlazorDevServerPackageVersion}" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="${MicrosoftAspNetCoreBlazorHttpClientPackageVersion}" /> - <PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="${MicrosoftAspNetCoreComponentsAuthorizationPackageVersion}" Condition="'$(IndividualLocalAuth)' == 'true'" /> </ItemGroup> <!--#if Hosted --> <ItemGroup> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in index dd9965626c1f..5fe7473679dc 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in @@ -13,21 +13,4 @@ <ProjectReference Include="..\Shared\BlazorWasm-CSharp.Shared.csproj" /> </ItemGroup> - <!--#if (IndividualLocalAuth && !UseLocalDB) --> - <ItemGroup> - <None Update="app.db" CopyToOutputDirectory="PreserveNewest" ExcludeFromSingleFile="true" /> - </ItemGroup> - - <!--#endif --> - <!--#if (IndividualLocalAuth) --> - <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="${MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion}" /> - <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="${MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion}" /> - <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="${MicrosoftAspNetCoreIdentityUIPackageVersion}" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="${MicrosoftEntityFrameworkCoreSqlServerPackageVersion}" Condition="'$(UseLocalDB)' == 'True'" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="${MicrosoftEntityFrameworkCoreSqlitePackageVersion}" Condition="'$(UseLocalDB)' != 'True'" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="${MicrosoftEntityFrameworkCoreToolsPackageVersion}" /> - </ItemGroup> - - <!--#endif --> </Project> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj index 5ae2bfe6cac2..65457a000d35 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj @@ -20,15 +20,9 @@ MicrosoftAspNetCoreBlazorBuildPackageVersion=$(MicrosoftAspNetCoreBlazorBuildPackageVersion); MicrosoftAspNetCoreBlazorDevServerPackageVersion=$(MicrosoftAspNetCoreBlazorDevServerPackageVersion); MicrosoftAspNetCoreBlazorHttpClientPackageVersion=$(MicrosoftAspNetCoreBlazorHttpClientPackageVersion); - MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion); - MicrosoftAspNetCoreComponentsAuthorizationPackageVersion=$(MicrosoftAspNetCoreComponentsAuthorizationPackageVersion); - MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion=$(MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion); - MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion=$(MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion); - MicrosoftAspNetCoreIdentityUIPackageVersion=$(MicrosoftAspNetCoreIdentityUIPackageVersion); - MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); - MicrosoftEntityFrameworkCoreSqlitePackageVersion=$(MicrosoftEntityFrameworkCoreSqlitePackageVersion); - MicrosoftEntityFrameworkCoreToolsPackageVersion=$(MicrosoftEntityFrameworkCoreToolsPackageVersion); MonoWebAssemblyInteropPackageVersion=$(MonoWebAssemblyInteropPackageVersion); + MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion); + MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion); </GeneratedContentProperties> </PropertyGroup> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json index 38651820f211..4e89e1d2dca8 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json @@ -5,31 +5,11 @@ "longName": "no-restore", "shortName": "" }, - "Hosted": { - "longName": "hosted" - }, + "Hosted": { + "longName": "hosted" + }, "Framework": { "longName": "framework" - }, - "UseLocalDB": { - "longName": "use-local-db" - }, - "HttpPort": { - "isHidden": true - }, - "HttpsPort": { - "isHidden": true - }, - "ExcludeLaunchSettings": { - "longName": "exclude-launch-settings", - "shortName": "" - }, - "UserSecretsId": { - "isHidden": true - }, - "NoHttps": { - "longName": "no-https", - "shortName": "" } } -} +} \ No newline at end of file diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json index d2e1735f7e66..b6cb64fcec5f 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json @@ -74,82 +74,6 @@ "exclude": [ "*.sln" ] - }, - { - "condition": "(!IndividualLocalAuth || UseLocalDB)", - "exclude": [ - "Server/app.db" - ] - }, - { - "condition": "(!IndividualLocalAuth)", - "exclude": [ - "Server/Data/SqlLite/**", - "Server/Data/SqlServer/**", - "Server/Data/ApplicationDbContext.cs", - "Server/Areas/**" - ] - }, - { - "condition": "(IndividualLocalAuth && UseLocalDB)", - "rename": { - "Server/Data/SqlServer/": "Server/Data/Migrations/" - }, - "exclude": [ - "Server/Data/SqlLite/**" - ] - }, - { - "condition": "(IndividualLocalAuth && !UseLocalDB)", - "rename": { - "Server/Data/SqlLite/": "Server/Data/Migrations/" - }, - "exclude": [ - "Server/Data/SqlServer/**" - ] - }, - { - "condition": "(NoAuth && Hosted)", - "rename": { - "Client/Shared/MainLayout.NoAuth.razor": "Client/Shared/MainLayout.razor" - }, - "exclude": [ - "Client/Shared/LoginDisplay.*.razor", - "Client/Shared/MainLayout.Auth.razor" - ] - }, - { - "condition": "(!Hosted)", - "rename": { - "Client/Shared/MainLayout.NoAuth.razor": "Shared/MainLayout.razor" - }, - "exclude": [ - "Client/Shared/LoginDisplay.*.razor", - "Client/Shared/MainLayout.Auth.razor" - ] - }, - { - "condition": "(!NoAuth && Hosted)", - "rename": { - "Client/Shared/MainLayout.Auth.razor": "Client/Shared/MainLayout.razor" - }, - "exclude": [ - "Client/Shared/MainLayout.NoAuth.razor" - ] - }, - { - "condition": "(IndividualLocalAuth)", - "rename": { - "Client/Shared/LoginDisplay.IndividualLocalAuth.razor": "Client/Shared/LoginDisplay.razor" - } - }, - { - "condition": "(NoAuth)", - "exclude": [ - "Client/Services/HostAuthenticationStateProvider.cs", - "Server/Controllers/UserController.cs", - "Shared/Authorization/*" - ] } ] } @@ -183,111 +107,6 @@ "datatype": "bool", "defaultValue": "false", "description": "If specified, includes an ASP.NET Core host for the Blazor app." - }, - "auth": { - "type": "parameter", - "datatype": "choice", - "choices": [ - { - "choice": "None", - "description": "No authentication" - }, - { - "choice": "Individual", - "description": "Individual authentication" - } - ], - "defaultValue": "None", - "description": "The type of authentication to use" - }, - "UserSecretsId": { - "type": "parameter", - "datatype": "string", - "replaces": "aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502", - "defaultValue": "aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502", - "description": "The ID to use for secrets (use with OrgReadAccess or Individual auth)." - }, - "ExcludeLaunchSettings": { - "type": "parameter", - "datatype": "bool", - "defaultValue": "false", - "description": "Whether to exclude launchSettings.json from the generated template." - }, - "HttpPort": { - "type": "parameter", - "datatype": "integer", - "description": "Port number to use for the HTTP endpoint in launchSettings.json." - }, - "HttpPortGenerated": { - "type": "generated", - "generator": "port" - }, - "HttpPortReplacer": { - "type": "generated", - "generator": "coalesce", - "parameters": { - "sourceVariableName": "HttpPort", - "fallbackVariableName": "HttpPortGenerated" - }, - "replaces": "8080" - }, - "HttpsPort": { - "type": "parameter", - "datatype": "integer", - "description": "Port number to use for the HTTPS endpoint in launchSettings.json. This option is only applicable when the parameter no-https is not used (no-https will be ignored if either IndividualAuth or OrganizationalAuth is used)." - }, - "HttpsPortGenerated": { - "type": "generated", - "generator": "port", - "parameters": { - "low": 44300, - "high": 44399 - } - }, - "HttpsPortReplacer": { - "type": "generated", - "generator": "coalesce", - "parameters": { - "sourceVariableName": "HttpsPort", - "fallbackVariableName": "HttpsPortGenerated" - }, - "replaces": "44300" - }, - "IndividualLocalAuth": { - "type": "computed", - "value": "(auth == \"Individual\")" - }, - "NoAuth": { - "type": "computed", - "value": "(!(IndividualAuth))" - }, - "IndividualAuth": { - "type": "computed", - "value": "(IndividualLocalAuth)" - }, - "RequiresHttps": { - "type": "computed", - "value": "(IndividualAuth || !NoHttps)" - }, - "NoHttps": { - "type": "parameter", - "datatype": "bool", - "defaultValue": "false", - "description": "Whether to turn off HTTPS. This option only applies if Individual, IndividualB2C, SingleOrg, or MultiOrg aren't used for --auth." - }, - "UseLocalDB": { - "type": "parameter", - "datatype": "bool", - "defaultValue": "false", - "description": "Whether to use LocalDB instead of SQLite. This option only applies if --auth Individual or --auth IndividualB2C is specified." - }, - "copyrightYear": { - "type": "generated", - "generator": "now", - "replaces": "copyrightYear", - "parameters": { - "format": "yyyy" - } } }, "tags": { diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json index cbed84838b4e..5cb50d10a519 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json @@ -18,30 +18,6 @@ "additionalWizardParameters": { "$isMultiProjectTemplate$": "true" }, - "supportedAuthentications": [ - { - "auth": "None", - "authenticationType": "NoAuth", - "allowUnsecured": true - }, - { - "auth": "Individual", - "authenticationType": "IndividualAuth", - "b2cAuthenticationOptions": "Local" - } - ], - "ports": [ - { - "name": "HttpPort", - "useHttps": false - }, - { - "name": "HttpsPort", - "useHttps": true - } - ], - "excludeLaunchSettings": false, - "disableHttpsSymbol": "NoHttps", "symbolInfo": [ { "id": "Hosted", diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor index 7b58ea096f72..1c360b7121a7 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor @@ -1,5 +1,4 @@ -@*#if (NoAuth) -<Router AppAssembly="@typeof(Program).Assembly"> +<Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> @@ -9,17 +8,3 @@ </LayoutView> </NotFound> </Router> -#else -<CascadingAuthenticationState> - <Router AppAssembly="@typeof(Program).Assembly"> - <Found Context="routeData"> - <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> - </Found> - <NotFound> - <LayoutView Layout="@typeof(MainLayout)"> - <p>Sorry, there's nothing at this address.</p> - </LayoutView> - </NotFound> - </Router> -</CascadingAuthenticationState> -#endif*@ diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor index 99cda40a53b0..0faf18fefd34 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor @@ -1,13 +1,7 @@ @page "/fetchdata" -@*#if (!NoAuth) -@using Microsoft.AspNetCore.Authorization -#endif*@ @*#if (Hosted) @using BlazorWasm_CSharp.Shared #endif*@ -@*#if (!NoAuth) -@attribute [Authorize] -#endif*@ @inject HttpClient Http <h1>Weather forecast</h1> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs index 06790b9c57c6..5790d212dcde 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs @@ -4,9 +4,6 @@ using System.Text; using Microsoft.AspNetCore.Blazor.Hosting; using Microsoft.Extensions.DependencyInjection; -#if (!NoAuth) -using Microsoft.AspNetCore.Components.Authorization; -#endif #if (Hosted) namespace BlazorWasm_CSharp.Client @@ -21,13 +18,6 @@ public static async Task Main(string[] args) var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("app"); - // use builder.Services to configure application services. -#if (IndividualLocalAuth) - builder.Services.AddOptions(); - builder.Services.AddAuthorizationCore(); - builder.Services.AddSingleton<AuthenticationStateProvider, HostAuthenticationStateProvider>(); -#endif - await builder.Build().RunAsync(); } } diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs deleted file mode 100644 index efb2cd636d9d..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Services/HostAuthenticationStateProvider.cs +++ /dev/null @@ -1,56 +0,0 @@ -using BlazorWasm_CSharp.Shared.Authorization; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Authorization; -using System.Net.Http; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace BlazorWasm_CSharp.Client -{ - public class HostAuthenticationStateProvider : AuthenticationStateProvider - { - private readonly HttpClient _client; - private ClaimsPrincipal _currentUser; - - public HostAuthenticationStateProvider(HttpClient client) - { - _client = client; - } - - public override async Task<AuthenticationState> GetAuthenticationStateAsync() - { - if (_currentUser == null) - { - await FetchUser(); - } - - return new AuthenticationState(_currentUser); - } - - private async Task FetchUser() - { - var user = await _client.GetJsonAsync<UserInfo>("User"); - - if (!user.IsAuthenticated) - { - _currentUser = new ClaimsPrincipal(new ClaimsIdentity()); - return; - } - - var identity = new ClaimsIdentity( - nameof(HostAuthenticationStateProvider), - user.NameClaimType, - user.RoleClaimType); - - if (user.Claims != null) - { - foreach (var claim in user.Claims) - { - identity.AddClaim(new Claim(claim.Type, claim.Value)); - } - } - - _currentUser = new ClaimsPrincipal(identity); - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor deleted file mode 100644 index 25f9db264b4a..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/LoginDisplay.IndividualLocalAuth.razor +++ /dev/null @@ -1,12 +0,0 @@ -<AuthorizeView> - <Authorized> - <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a> - <form method="post" action="Identity/Account/LogOut"> - <button type="submit" class="nav-link btn btn-link">Log out</button> - </form> - </Authorized> - <NotAuthorized> - <a href="Identity/Account/Register">Register</a> - <a href="Identity/Account/Login">Log in</a> - </NotAuthorized> -</AuthorizeView> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor deleted file mode 100644 index fafa2f55f105..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.Auth.razor +++ /dev/null @@ -1,16 +0,0 @@ -@inherits LayoutComponentBase - -<div class="sidebar"> - <NavMenu /> -</div> - -<div class="main"> - <div class="top-row px-4 auth"> - <LoginDisplay /> - <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> - </div> - - <div class="content px-4"> - @Body - </div> -</div> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.NoAuth.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor similarity index 100% rename from src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.NoAuth.razor rename to src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor index fa501010b9f6..912a5070c2f4 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor @@ -1,7 +1,4 @@ @using System.Net.Http -@*#if (!NoAuth) -@using Microsoft.AspNetCore.Components.Authorization -#endif*@ @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/favicon.ico deleted file mode 100644 index a3a799985c43bc7309d701b2cad129023377dc71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85<eW@6XRp%jD>=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$Q<HOixSl<aTM__jl4#^thzg zR%8kDj}7!lG~6zIy}i=c(}UmYmfr3z>Fr9nP<Q2WYG!6yx=!tqj{N(it>g(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP<k8>8W}_qJ<Ai`=Ou7 z`ue&ogWfUli9DMc8&O<H4|y`$*Ck6>L$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}<eeQ3J;Ww5b2VCRhCywj)`%eE_;>C|iN7)YN`^)<MX{;gTi@1yp^{2@b;(+g` zAt&imr^?OutN&RNC7A!n)B63jwKbWao5ecJ%hKY!EZ~|jkF}#Ltw6^3x5~;&{eFM- zi;^sTLgE!Ky7P}i#{58fMnFeDcsGT0=<Dl~`uh4mC;g*M#nOM~MM+)Qlk@xhE}^NZ zQ9_}Rw6?bH#)oeiA0L;6g#`s(=X#N*<>h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F<Rt1N8OKCQyfy(wj_3Pa+10N>3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4<M8Hm<td$i zo%63^{uMj_JZyl2H|=@`4jvvW(-Ts0+?#)(Zm%@H_UF>{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{<Wz0W0IwJGaQ;Ngf)HrbH_i%t+ zRbG%E4pf{tRz1*<`LTY34f{a*UrA^`{Keb<8-DNe(tP~azWFT<h7USFe1h^|)$m|) zY*glF%>484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKn<s0*3P3iB*gT^a0vIzTZU|trn2Uv9c3Hh)9f3g4{&h?nbULpvN z96n^`Pp`^wOQE#w`Lc8replMCXK8)sOVV=kx5^vt9Vp{-(Alv;%nuxzF#i;MKYb4U zzQV*feDk<Wj*l6DJWwXMCX~$yAMpLrvcuJb0|Uy(;g%w4-TgPxaq!#HhPhjz2Q4Rm zgZUv_3Y>o;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?<y`V ztR5U35HLVSIse|TN~8$;o%g;jAzZhXzwF3Z8snPGVLi>B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskka<HNc) zw7%ikv18A{=YN3n^EKXnL?Q>iCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE<WT-@UlL8}x(!oZA8J5zU^H z^A9LLlqc{rSK**`!q^J#O?mF{`>*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YB<mKXAV!4?lsqzpK~nm2X@% zznz;rn1?^*{QmQRy*7FZTn2bH>Xz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FE<n#M zl!>e}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5a<V_m; zgjM+PrKKg|+4S7GbD8ri{bv3|(WAftcJSQ3j463m3!*jX9@l3SwsIJ9$n(_<d<V}- zdM?8m`TY6woc|B3{h0`#lz73zk}Uaq<w4i6rzBQ)?7HUX-1c18+m(<moCSvAXLye5 zh5c`8YLaL)x*b1$i#PuXiRV8kiNc2^j&+D1gdfb}|5oTH&30~%=gw3MWL>JOtL4<G zQ+geX#i}{CfBuEhxKIYkhY836$5h(|e8hWgX@2-7&O3^caOQNC+RsJA9=Z|lz!|j~ zzv!M%E&bjs-ql8b^FEb%#q+R*m6a8_c=4j1p}V@eu9_R)yao8k1Y%7=kV>U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09<pd zBG-35{NWG(mj@qs;K5x_@BH1ar=NZmqYF>(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<<HU zYqNw~nxvi3+#u~u4m8wBdt;r18fqQ5f-wkc<;fra!=7j)qI)jCZL`;m=MLi>t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32Z<i}p+w67N1l-O`bz9E2Q&Prl{J&c zFtWxN6yt(CUz#|WFBayHKRA5RSe_Guv1?%CbBu>AE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh<puUpgSc4h;a^JPcx88NIwB_wZ3>1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h<Y-#lOkKs1PG-dHahJ zM$9B!@NH=agbTkTEj7nH{j+*#V~1D+#UC`_oFZ}Me`Xv{@kczB_^%*-rLiN#^HvZC zW(<sHDV`^1p=WbA*Ya%3^OlV(W{)pCXZUY^cUfk7fj?qhj5jjg$(WPI9Nz{#c;9@! z)Zp*vi`o)@{L|5U;-82?ew;X@(E~@0um(f0$%}}ESvgw3SzYA_xsriy$PoeZL|V8W z{@A2<JtHqX_pFg0#+X+jKYhgiuT=-g|90fanqL15WCybU=I0>)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE<xtH<PVcLDjlozY_*>0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E<eJzSD0o_jT(!I%bYf7s+A4F4S&vU&{u zGbX8LWQ`N}<B$_Fk65OWB{ME!ZERdNV}zY};koB_$6`_N2)YHB>2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudx<WJi9vaTgF5Z9j)pgxL;;`&B{@bE%JPV^=rl!1jcq@Z#B+K zI|2CR^UoXk0q$!Sf5ta~Z|k1Fh3?+3@pjdRw-9@${9~P5058{|`@~;!oxq)E`a}o( z8TJsw+Xa=SEL)22TOOnx8*XCLjxTj%)P9=0>tDVA{K5Y<t}S3@pcVZ8Th-w<@*n!! z{5Iw1^Pc<=f6hypBmP*AsZr+1oqVnGKO_xxS8yg@lnLzHXK^lHLXLT2Y)od6$6zjW z9C6|q#F-b7CmbIcmKp4m7BvnvBs0jtGR{3Vggi9%Ow@12rlw(+%(c0Xy{wTRCzd-q z*e0R(?n0dVtJ1#zZi$pWqOotrym_zr!eLj|ROWD&A`Mex27eRR=>h*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u<d{7CivIL!OYgVGO<b{2`UIHP{i#n~qoq@_&@^AO(Z} z#dBx%d`SP8OeFNo#JyrN5tr_+l*A&Pl8ncsJC&4ZX9w(URJxP6hTSsP33H9_bi)@% zu_vKVG}rhHu7CFAlP>;@qs|V75Z^|Q0l0?teobTE8t<n*L#~=H98x(W?vyu^e<1&d zVCNt|KKw6VydWvylS1AzNdOH7;z|Q?cL6+10ul;Q-^lCSu>Gl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl<XIQZKGrvIGxelxgp{*E!yiZR}IrSkt->^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7<SN=BJIqx?5B)&%HI%7#(A9E*{D)1a zzF<__h-;n;xMv$>y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;o<tE{OE(?2=<A4MF}#OA>NNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ<hbA{CN2H;rvl^?u=Z#a9)8m2_BTo>56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK<z1EteZqA7EX64Ap4|63J zj4Um~{}W6Oi8&OL<FvV6o6oW%_Z}v%WpZ1@U(esz>-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+&<jfTRckhNg0e{@1{I9PYT{krFIt@FQ zg+FwG^sp{Y@uzMp4aUaWbr@wX&jIfL%sQAoAlG7w_&aAJ|2mvGb0(1gMt;7hdCnN> z>$*<vlz7PxQ0w-nB#-=5Lba8aRA*erxDLBLmXZInYq6sEvo_D#CSM*dTb3*>Hf}}y zkt@nLXFG9%v**s{z&{H4e?aq<G31K6PCl)5elgO3{9)UrlZrQaZ(c^0v}TWI7z^P2 zsLTIFwM(SQ+9#ebDO2=!Tnny)T?^fZ19!?2&qc&PopnY%cm7<U{45MZe<3%K{ohhL zm~)LF=iB)n^a1x;FCKO9wu8Z+e$vIAGyqou>p%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?<hi6;nFqt>!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w<CJ?O>;*RFm;XPDQwx%~;8i<oa^ zexLQs#C;Swe&jxL;2)Pn5quSD44CilIrSXYU_0#4b{VXBL&8lp8{)5e>BzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+t<Pf&d|V}H3F<zNPq^dnLw>P zX$aL;*^g$7<Ue(mJhn9?_FDN)+hp<2y0&!%%(W5co>UyM2Go+_4A+f)IQcy^G$h2E zb?nT$<GLCMXx=#+f8x!0hdAV2X~A_&-#?U7{;x-VC^O92Wb?eSzE+S6RX|=;&pC$< z9g@=0Qq9>XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&l<K=Dpmb{^4-!94u`ca zdNVoO>fae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)J<Y zxc^5t3qJV45B`taZ@>MCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAV<aixb6h<Sg0H6jw4qU zV~?Bz5!)*lmM-iqJqY1C7nsj&+qP{N{V-~a1^op#4Sw~jUm=fL>q0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`<T9_no>l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{<Jh_kyRt}|;t96pc-^Er3` zo}iC2gMPObPU{|m=x2|p6X&-wXJt%zkSPP3@xa!}dGs%8Jc%(S1BMS)CX6g%9UNV- z>v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKo<R02YmTL zqhr<%m_BFM7Fa&y947^SQ}y4{ZAaF|G`@C+sh521)5?cN^cOe0_9@gH-Y$)(pJd(P z_1X@lpSgXfMnLNXGU%rcETRu24v0w?{GLKAA}IoVUkW|qDfm7YI>X3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF<O6FlgJ{<Kj?Q@Wliwb+>?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*S<!No<o1d3X^w>tr(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-<?wRtMA$a{Uv^+e}~R^M`&pP`_w=4t2sW50+lDC-HjPUHYxxaYn6a!kV+c zpX(pPb74a0@ugg}?EV6381FQ7Pgs9Tw;k1Ys~vUZ0Q%wWr;HEDO@F2gSo*u52fF@{ z0q%z~Y=K`6U=z3xA^l!GtVgeR&-iJVe)8J~tTk;$y|}FzXPtY??k~a~!Uo`(3(c&V z#ovwmXW9;9NBlZr@{{g90y1FeXN>^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqz<CJIAM$L1BM%w-GTk@RUOM3L%cGxlX&$hqjP-p4?g8S* zf2wthE%1v3ttI8(g6O9&p&r4WTH3u4^(Uy`C@Z$~Z!QCFO|beXXOCj#AWIfZKZ&zf zwlZ<mX#YOv`9G~&1pUsa&k{hbqt<3(t(AT}<AbzwZ(!($j*x!R8U(=C*57b6bs&@n z(qG`LzmNXS_5(h-GP;nxKcZc<fIT|*=|N!k@%Sua0Na&@Ec*Fei5AudgZ5_Zb=dRL zy5~!dP56w~t?J)Mzt3*i+F{ENmwwIvn;HPhLRoR4kA5Ey0`~*<Tu44!-QpM^3mNiY zd69ec=!ec>FJ?h&Dk<xHrU>@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK<T$Q z`bO#l_@MP@_8AMlIwG!r58^)LK@V~`<U<c)KlBAULJoQm1LD58CzVp$)XfpU%erPW z8sA`jr0x}Uuf#ng_s;N@pg(vtd+S{Ehw)4s))#8cIdmaez5{i`_h`*|+aA>1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8<r-Iaf>U4i~PI>7a3{kVa8<kbN6eyGEHKpnx06E+}DNbur?yk^WW2oOhPEHMzw z=X22?2K^zfKk0w-3x<B|f7Kqq?vehsJ&ym&vK>|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{<?)|7`m4UeEKeU77W{UX5;9iATSc1JZBhfY1KP&`I@+zH<_On{%uq zN9diKefHP4moxi1V~=fpz8!PYj~a2-Rue*yfn@o1>3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpN<VbL&~J6p@r$}YA`b%i;P8Su%#HYA>E=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye<Hud7yLjT^qdxgMfvTOvezVxCTF3Oif0G_WIV`7|<P~nWc ze(AR_33^2C!`bid4}IuE|D80@5BovapS?PO_T6`4{db`M<z8uj=gZLlJGJM6&pb2V z_4I~1<lonN^!s_xCx=V%oYNfrBiZ*!d-lDc_piSEqKx(?Wdva3^UN8rzr^2Ta=Q97 zbMnl0{t<JZx`tWn&mJE>+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB<q)&YlUNAEf(Uu_DAf!GkDzUD%_;=Nj{#_Uqt1dtf5y z;SZ7>(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZ<YY5zOXFUQ`X@ZP(W z{s{U%j85F8y<6<33tE5Ak68a_c;MC|yL{ktG|gVY^ADbn^!84m*MEMxiVt3lk+CKA zNb%h3<?@Xjs4RdF=h6F?ZU20tua_~bKYP8{-xA*Y4e7!9EB(0Udp_^a`hUOO;5Gl# z5jHhr?F00{?z@eCP$vBJ+iSab%;E!Oz$Xi%DibEYrm<#?yF0OWCss@zphsqN`q5Lu zz8>v)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=K<Q;83+yZ2l>S2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaP<Ja6qEsn*3Id6d4Rqr z^l|y<AEzB~*WX9~0M>tHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hz<pvTgWaXk$=0q8wlZ_?`kYW{7!0CX>d{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(<m44z)dfXB6&vU2slR>oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v<nWs((bE+M|w5L=Us_;lY2i^s{%yg6)%J4-lXC#CZGW^gpJ(s_ajV?!O=O z|C7?MHi32l&s(N{*pmI<M2@dV_Wj@S_qE!d#UR?*C(6D*_Cak*KlNXGMIrBy1N}FN z@XUh*`bF7$*>&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2<b;m*$JK^VtIU_Y$NB`p^DNyaH+G z{mp3Lmvg;t<h!|kGyA^37d!i!w9>{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_<!%{oZJ8a diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml deleted file mode 100644 index 21b7fe273450..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Account/LogOut.cshtml +++ /dev/null @@ -1,15 +0,0 @@ -@page -@using Microsoft.AspNetCore.Identity -@attribute [IgnoreAntiforgeryToken] -@inject SignInManager<IdentityUser> SignInManager -@functions { - public async Task<IActionResult> OnPost() - { - if (SignInManager.IsSignedIn(User)) - { - await SignInManager.SignOutAsync(); - } - - return Redirect("~/"); - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml deleted file mode 100644 index a4f854aac31f..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml +++ /dev/null @@ -1,27 +0,0 @@ -@using Microsoft.AspNetCore.Identity -@inject SignInManager<IdentityUser> SignInManager -@inject UserManager<IdentityUser> UserManager -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - -<ul class="navbar-nav"> -@if (SignInManager.IsSignedIn(User)) -{ - <li class="nav-item"> - <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a> - </li> - <li class="nav-item"> - <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="/" method="post"> - <button type="submit" class="nav-link btn btn-link text-dark">Logout</button> - </form> - </li> -} -else -{ - <li class="nav-item"> - <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a> - </li> - <li class="nav-item"> - <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a> - </li> -} -</ul> diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs deleted file mode 100644 index 6c27a4ad7c4f..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/UserController.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using BlazorWasm_CSharp.Shared.Authorization; - -namespace BlazorWasm_CSharp.Server.Controllers -{ - [ApiController] - public class UserController : ControllerBase - { - [HttpGet("/User")] - [Authorize] - [AllowAnonymous] - public IActionResult GetCurrentUser() => - Ok(User.Identity.IsAuthenticated ? CreateUserInfo(User) : UserInfo.Anonymous); - - private UserInfo CreateUserInfo(ClaimsPrincipal claimsPrincipal) - { - if (!claimsPrincipal.Identity.IsAuthenticated) - { - return UserInfo.Anonymous; - } - - var userInfo = new UserInfo(); - userInfo.IsAuthenticated = true; - - if (claimsPrincipal.Identity is ClaimsIdentity claimsIdentity) - { - userInfo.NameClaimType = claimsIdentity.NameClaimType; - userInfo.RoleClaimType = claimsIdentity.RoleClaimType; - } - else - { - userInfo.NameClaimType = "name"; - userInfo.RoleClaimType = "roles"; - } - - if (claimsPrincipal.Claims.Any()) - { - var claims = new List<ClaimValue>(); - var nameClaims = claimsPrincipal.FindAll(userInfo.NameClaimType); - foreach (var claim in nameClaims) - { - claims.Add(new ClaimValue(userInfo.NameClaimType, claim.Value)); - } - - // Uncomment this code if you want to send additional claims to the client. - //foreach (var claim in claimsPrincipal.Claims.Except(nameClaims)) - //{ - // claims.Add(new ClaimValue(claim.Type, claim.Value)); - //} - - userInfo.Claims = claims; - } - - return userInfo; - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs index c6f2eb0ecebe..6862c16a71b3 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs @@ -3,17 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -#if (!NoAuth) -using Microsoft.AspNetCore.Authorization; -#endif using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace BlazorWasm_CSharp.Server.Controllers { -#if (!NoAuth) - [Authorize] -#endif [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs deleted file mode 100644 index 81390814c564..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/ApplicationDbContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; - -namespace BlazorWasm_CSharp.Server.Data -{ - public class ApplicationDbContext : IdentityDbContext - { - public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) - : base(options) - { - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs deleted file mode 100644 index 7bea3b5b34bc..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs +++ /dev/null @@ -1,270 +0,0 @@ -// <auto-generated /> -using System; -using BlazorWasm_CSharp.Server.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("00000000000000_CreateIdentitySchema")] - partial class CreateIdentitySchema - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0"); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property<string>("Id") - .HasColumnType("TEXT"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property<string>("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property<string>("ClaimType") - .HasColumnType("TEXT"); - - b.Property<string>("ClaimValue") - .HasColumnType("TEXT"); - - b.Property<string>("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property<string>("Id") - .HasColumnType("TEXT"); - - b.Property<int>("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property<string>("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<bool>("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property<bool>("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property<DateTimeOffset?>("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property<string>("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("PasswordHash") - .HasColumnType("TEXT"); - - b.Property<string>("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property<bool>("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property<string>("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property<bool>("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property<string>("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property<string>("ClaimType") - .HasColumnType("TEXT"); - - b.Property<string>("ClaimValue") - .HasColumnType("TEXT"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.Property<string>("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("TEXT"); - - b.Property<string>("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("TEXT"); - - b.Property<string>("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs deleted file mode 100644 index 1df0c12752ef..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/00000000000000_CreateIdentitySchema.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - public partial class CreateIdentitySchema : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column<string>(nullable: false), - Name = table.Column<string>(maxLength: 256, nullable: true), - NormalizedName = table.Column<string>(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column<string>(nullable: false), - UserName = table.Column<string>(maxLength: 256, nullable: true), - NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true), - Email = table.Column<string>(maxLength: 256, nullable: true), - NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true), - EmailConfirmed = table.Column<bool>(nullable: false), - PasswordHash = table.Column<string>(nullable: true), - SecurityStamp = table.Column<string>(nullable: true), - ConcurrencyStamp = table.Column<string>(nullable: true), - PhoneNumber = table.Column<string>(nullable: true), - PhoneNumberConfirmed = table.Column<bool>(nullable: false), - TwoFactorEnabled = table.Column<bool>(nullable: false), - LockoutEnd = table.Column<DateTimeOffset>(nullable: true), - LockoutEnabled = table.Column<bool>(nullable: false), - AccessFailedCount = table.Column<int>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column<int>(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - RoleId = table.Column<string>(nullable: false), - ClaimType = table.Column<string>(nullable: true), - ClaimValue = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column<int>(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column<string>(nullable: false), - ClaimType = table.Column<string>(nullable: true), - ClaimValue = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column<string>(maxLength: 128, nullable: false), - ProviderKey = table.Column<string>(maxLength: 128, nullable: false), - ProviderDisplayName = table.Column<string>(nullable: true), - UserId = table.Column<string>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column<string>(nullable: false), - RoleId = table.Column<string>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column<string>(nullable: false), - LoginProvider = table.Column<string>(maxLength: 128, nullable: false), - Name = table.Column<string>(maxLength: 128, nullable: false), - Value = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 01098a9b9f9d..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlLite/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,268 +0,0 @@ -// <auto-generated /> -using System; -using BlazorWasm_CSharp.Server.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0"); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property<string>("Id") - .HasColumnType("TEXT"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property<string>("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property<string>("ClaimType") - .HasColumnType("TEXT"); - - b.Property<string>("ClaimValue") - .HasColumnType("TEXT"); - - b.Property<string>("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property<string>("Id") - .HasColumnType("TEXT"); - - b.Property<int>("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property<string>("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<bool>("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property<bool>("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property<DateTimeOffset?>("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property<string>("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property<string>("PasswordHash") - .HasColumnType("TEXT"); - - b.Property<string>("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property<bool>("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property<string>("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property<bool>("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property<string>("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property<string>("ClaimType") - .HasColumnType("TEXT"); - - b.Property<string>("ClaimValue") - .HasColumnType("TEXT"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.Property<string>("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("TEXT"); - - b.Property<string>("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("TEXT"); - - b.Property<string>("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property<string>("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs deleted file mode 100644 index f1d1fc3f8c40..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs +++ /dev/null @@ -1,277 +0,0 @@ -// <auto-generated /> -using System; -using BlazorWasm_CSharp.Server.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("00000000000000_CreateIdentitySchema")] - partial class CreateIdentitySchema - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property<string>("Id") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property<string>("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property<string>("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property<string>("Id") - .HasColumnType("nvarchar(450)"); - - b.Property<int>("AccessFailedCount") - .HasColumnType("int"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property<string>("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<bool>("EmailConfirmed") - .HasColumnType("bit"); - - b.Property<bool>("LockoutEnabled") - .HasColumnType("bit"); - - b.Property<DateTimeOffset?>("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property<string>("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property<bool>("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property<string>("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property<bool>("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property<string>("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property<string>("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.Property<string>("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("ProviderKey") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs deleted file mode 100644 index eb6f88d7cb90..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/00000000000000_CreateIdentitySchema.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - public partial class CreateIdentitySchema : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column<string>(nullable: false), - Name = table.Column<string>(maxLength: 256, nullable: true), - NormalizedName = table.Column<string>(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column<string>(nullable: false), - UserName = table.Column<string>(maxLength: 256, nullable: true), - NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true), - Email = table.Column<string>(maxLength: 256, nullable: true), - NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true), - EmailConfirmed = table.Column<bool>(nullable: false), - PasswordHash = table.Column<string>(nullable: true), - SecurityStamp = table.Column<string>(nullable: true), - ConcurrencyStamp = table.Column<string>(nullable: true), - PhoneNumber = table.Column<string>(nullable: true), - PhoneNumberConfirmed = table.Column<bool>(nullable: false), - TwoFactorEnabled = table.Column<bool>(nullable: false), - LockoutEnd = table.Column<DateTimeOffset>(nullable: true), - LockoutEnabled = table.Column<bool>(nullable: false), - AccessFailedCount = table.Column<int>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column<int>(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - RoleId = table.Column<string>(nullable: false), - ClaimType = table.Column<string>(nullable: true), - ClaimValue = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column<int>(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - UserId = table.Column<string>(nullable: false), - ClaimType = table.Column<string>(nullable: true), - ClaimValue = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column<string>(maxLength: 128, nullable: false), - ProviderKey = table.Column<string>(maxLength: 128, nullable: false), - ProviderDisplayName = table.Column<string>(nullable: true), - UserId = table.Column<string>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column<string>(nullable: false), - RoleId = table.Column<string>(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column<string>(nullable: false), - LoginProvider = table.Column<string>(maxLength: 128, nullable: false), - Name = table.Column<string>(maxLength: 128, nullable: false), - Value = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 07026c1264ee..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Data/SqlServer/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,275 +0,0 @@ -// <auto-generated /> -using System; -using BlazorWasm_CSharp.Server.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace BlazorWasm_CSharp.Server.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property<string>("Id") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property<string>("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property<string>("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property<string>("Id") - .HasColumnType("nvarchar(450)"); - - b.Property<int>("AccessFailedCount") - .HasColumnType("int"); - - b.Property<string>("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property<string>("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<bool>("EmailConfirmed") - .HasColumnType("bit"); - - b.Property<bool>("LockoutEnabled") - .HasColumnType("bit"); - - b.Property<DateTimeOffset?>("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property<string>("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property<string>("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property<bool>("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property<string>("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property<bool>("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property<string>("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property<string>("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.Property<string>("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("ProviderKey") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.Property<string>("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property<string>("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property<string>("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs index eb96bae0e856..ac46fb46ddb3 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs @@ -1,53 +1,18 @@ using Microsoft.AspNetCore.Builder; -#if (IndividualLocalAuth) -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI; -#endif -#if (RequiresHttps) -using Microsoft.AspNetCore.HttpsPolicy; -#endif using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.ResponseCompression; -#if (IndividualLocalAuth) -using Microsoft.EntityFrameworkCore; -#endif -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Linq; -#if (IndividualLocalAuth) -using BlazorWasm_CSharp.Server.Data; -#endif namespace BlazorWasm_CSharp.Server { public class Startup { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { -#if (IndividualLocalAuth) - services.AddDbContext<ApplicationDbContext>(options => -#if (UseLocalDB) - options.UseSqlServer( - Configuration.GetConnectionString("DefaultConnection"))); -#else - options.UseSqlite( - Configuration.GetConnectionString("DefaultConnection"))); -#endif - services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) - .AddEntityFrameworkStores<ApplicationDbContext>(); - -#endif services.AddMvc(); services.AddResponseCompression(opts => { @@ -64,41 +29,17 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); -#if (IndividualLocalAuth) - app.UseDatabaseErrorPage(); -#endif app.UseBlazorDebugging(); } - else - { - app.UseExceptionHandler("/Error"); -#if (RequiresHttps) - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); -#else - } -#endif app.UseStaticFiles(); app.UseClientSideBlazorFiles<Client.Program>(); app.UseRouting(); -#if (IndividualLocalAuth) - app.UseAuthentication(); - app.UseAuthorization(); - -#endif app.UseEndpoints(endpoints => { -#if (IndividualLocalAuth) - endpoints.MapRazorPages(); -#endif - endpoints.MapControllers(); - + endpoints.MapDefaultControllerRoute(); endpoints.MapFallbackToClientSideBlazor<Client.Program>("index.html"); }); } diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/app.db deleted file mode 100644 index ec163057f1f5433ac77fa2fea05aa4a544e6ded0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106496 zcmeI)UvJyi83$m|b|g!-Eay+dt-w&02G$6+i)2IL6<Ft~GL;aPDMyk68%3cp5|a>- zL`S5Yx<CuaZh{m8cDb8=g8>5y<hpn5%`UgAeTrQ+Los0I@Q@-8MOhBo42$p+;zZ;j z4_`j-dk!U&NbPpnbPVa9)$8bv^y|cOLJ$(am!w1@F++adBtQOZnY@|v7s$Ut=>532 zGl}(oKf6FT&iz2Q`C0CVrLPtbvtOpaUwnW5^ZB*p^SN)6y_v7)p3JDicS0fY&A6^& z)(?csDY39F4Bj@oE#nh)zfrIcHN)Anjb7QhZ+7hleXF*jtFIKRN};Yus<x%<OY-;~ zWvQY`a&&iDx+b%Z<@`XnG&Y7}TQ@tSF|gH_&xnEBF&YDF<YTxP8$;D<8(vrRt?v-5 zzBDF=V2cLZF&snCNMrEY^Tu*Yd}l=%WZhKIwVK{BRGJsYM_1Vw`2%vBMUP?A?loGN zZSzy3MZ1&pr`4sDxVkDl{m9Ypwv8Y&ZugPJoOiT(;lr{LPNTaq={}p0$ji^AR9E)v zl2#!<d*$+)*GRWjTXJk;v7*)L)q<+kC3$x{RDIq7cB|@6p?V-~D+fWztVu&O?-=23 zN+aEP-MU>4(^0Ba74@d(_3Xu%m#RuhsVZ7gsrjetMRH9h=a8q>yrq;CQu@V0tytJn zUM2!s@_seT5+8v-9AYAHccZzCk06`Le~?Rxw^xOPTRQfmHkpwcdf&0!<)~`oMkLG2 zr>l!8aeZBQnvT>2n*)N)*>ZMVRj}ruEZpVYo^@olj9z>J$bR#-aXev*Ez>@1>&I>x zyT#-em`C?=1?I=fR~R2LDYS5S`ANBEeTKYWNwPPyNwKy*IoVz`p=`4?OD9JQZn~em z6-hUn>VkB$<;8L79?qlQK&OM8jAZ4eQXNhLQg~=`Bi!FRoPfe!y`pO5csq(#_tWcc zSU)~ASbcD-@96D*Wc_)oftx2-Ft0juyO|`NdJkN7Z<yM~qrTB?8j-~X4n5L%txKlz zHL_>^<S0FwN;+e)6Jn_hmNQ(h-eoyx4o2?zQyJd-r%om9n?@3MSqazGFqJ_tuXN5Q zGwv6gsg$^~B0N(fW5^DMk3Ap9?a$_+LBpNj_z^>{=OJN#92A<Qc<hpHwvATN>UW*d zLFjK<w7SiHuSd%5xaR1cLw-Oh9nwe4Dzeu-v)3_VMz`N_*=jzt`i|12A1ThWotIR9 z|KLMPOb|gMr5m08cXiu-Z1q~Vbo&7x{_X>-YiRw>UH|IiA1~B!j<c&7M9p;K%<7M= zlHPQz-o#VqV<#2#-h5J2S0+#6cKCX2r%$e4a7X-UBT{&E>!HyNRUcbUjw?ad9E|w0 zrcIf@EXIyUIY`WK^7pw%XX)_h<*o{TSfN7aKKSvGkPEbX*gWyvOrGzu$c_+3WouFc zZPp#qC(V#7ol!hg_w8Jqr`r-xj!aqcL)zObbf&)7+2b^T_O}m4NYF+rY;JOexk30C z?!tw^zK{|(HiVOk>(FQ@r5*ErPj^hKYu_?$QtijFD`$9{*lhx(VV@JZ#&i?|M?S5! z`c3B!`It?Dja)d0h&q!LKi(KO=3<Z2xDmU0mVKMPx{xJrgxo(8<PTmDfB*y_009U< z00Izz00bZa0SLT40;|GoO}x&%8pWQWJLH$qM%SUg32Z(vI{J-wufO}N3^^|$_s<0R zgBJuK009U<00Izz00bZa0SG_<0<W9EFK26M?sov!V}A)i@BfpB{_%nU1Rwwb2tWV= z5P$##AOHafKwydm=>30u|DWOn<J2Gk0SG_<0uX=z1Rwwb2tWV=L;&~yQ3eoz00bZa z0SG_<0uX=z1Rwx`=@-EL|LM;$&JY3+fB*y_009U<00Izz00ba_`~Ro`2tWV=5P$## zAOHafKmY;|fWY(%;Qs&g=NM-Q0SG_<0uX=z1Rwwb2tWV=5WxL^)Bpq^009U<00Izz z00bZa0SG`~`UUX)fBJKbGlT#HAOHafKmY;|fB*y_009W#`#)*`0uX=z1Rwwb2tWV= z5P$##ATa#``2IirImQ`600Izz00bZa0SG_<0uX=z1n~d=p#~rT0SG_<0uX=z1Rwwb z2tWV=(=UMg|I?pioFN1t009U<00Izz00bZa0SG_<_y17?5P$##AOHafKmY;|fB*y_ z0D<Wj!1w>@&oRyr0uX=z1Rwwb2tWV=5P$##Ab{`xr~wE-00Izz00bZa0SG_<0uX?} z^b6qo|Mce=X9xiZKmY;|fB*y_009U<00I!e_kYv?1Rwwb2tWV=5P$##AOHafKw$a> z@cn=KbBr^D00bZa0SG_<0uX=z1Rwwb2xN0F5(~-aiKV~i{+j*U(pQUz*)P-IFTOwj z`TSb)`P{e3-pto?Pi9o%JE4&HCh<F7?6WH=adTA|{KD+Ej8D}4M!`PR3}??adR41! z*bVx(+KQ}wqgYi6bwyIOEoEPl$L=Oe6-|;OJIm5Fne{5?2g2o)SXdVZZ;u|oY~44z zc7uiz4uGw`az+H)j?oZUBaMM|Ok=n-HilwbH#?&-u+^8(h=JQN8Ut(OW4IU_19kGc z3MV31eQ8V#!4_Ty!!ZPn;anKYDe;{ZVUTrGLATNLj-k@JU>T&V?2G&Xxy_=-uxa<2 z)$8bO^HZZmyOZ;|7jv`X>Z<VcBS*j6HX_9lS<HDys~0{jD{+;S%}C_s=TfRG`*lgH zke|JBdChC2F{&*&wy{{zYV~SC)#{SGyB)25S=z0tJB8|jw5=QjC9@_C3)nkGxSP^Q zH(s}{-!L7eN>x#BYF^J?jCrZ5l$5HX6_uKQy6$dNlAJ@H4yY}qtdPN1EYymHE#+k* zpe65Dvn=ru_`@M40(ZCZ5o9y@4{}NI_NtI@OUHiHHXWm(_Z`b!j;c0pM6$e`dm;Qw zTwfQSrXw}MMr*J+Th5NFis9h)GVd<$_N*hbW%S|;K=zxrjpGShY?=09TR(Qo*exc% zz&yH_D=<G+zQXv3Nuh<q%TLNR>oes2N|L>qO^UVk$;tMj31yqDSvomdNYQjZc`K4` zHq`~`X3LA?(mk9<y>!z-PDZkFQ>hLo0VzB*xe@N~9Zo=DuU=6#a=aZytNZD7H>@8Y z8mvCJ)pzuEKeGP3)xgaYESOiFx!p{XPQ3>%yEja2<5Az}HjT*Q0*4-Hyw)XC`5M_X ze{z%_O(mVN*a@*z2Fn?)SMQTS&`jo-mriAP@1HuAwD0p=IfkhWf_bHLKACa9*i5Cw zl@;Nc5*b5wFnsL!IBtJ74@q;E&G93KT+c(o{x~Q!N%7bv-E14JqSfy@ql3`jv}kpk z{a%lh+i}g&JBR#$QaYrMm{nx2duFd=#Efpg<FeI!X!RYXOFvSaXFKoXfWLq6Atfe= zppnvzPXD{QZ9lepty{YNfDeE7fz>s%e&?=#_3@7vYB<N))eNF$I&o(8$5u&iI#zGu zsq?Xu3VLroDXJ@zr*S)cy|&XQS1-6D{<IM(yt?(!=!U9~Ehop7AZrdr{8`hc%wHB` zFSK%ynBnB_bC1r_W3LK+SfN7aKKSvGkPEbX*gWyvOrGzu$c_+3WouFcZPp#qC(V#7 zol!hg_w8Jqr`r-xj!aqcL)zObbf&)7+2b^T_O}m4NYF+rY;JOexk30C?!tw^zK{|( zHiVOk>(FQ@r5*ErPj^hKYu_?$QtijFD`$9{*lhx(VV@JZ#&i?|M?S5!`c3B!`It?D zWs||M8i|NHlN3MR7&qo(kJGpjyLy&<kDsUC<#GR?|BVKgAOHafKmY;|fB*y_009U< z00Pq}kR>OzIRBf(Qg!L#;%^uJv+(DIOPN1qGU-327w7*%8t{Su1Rwwb2tWV=p1`5V z9`{;tpV9H}4u&50qO0sTy;~}KntFS0_`n~xb@-_-cOP<#CG^ynzpb4A!_}1dHhI7- z?H<v+(HcG6&%MKW4;BX7OgIR;Yn%V<jR{XP(qO_56S_B?ME;;LPcyRJqA_^)&w?ij z@h~MGresfy<o`zxQ~t>3?oO*qDLjiAeG-z6YjRKcb$u4|M?ao-y1M8-;en?yM;`Y0 zKYSV!_y6&c4gwH>00bZa0SG_<0uX=z1RyZ|0{H$v{W-=NLI45~fB*y_009U<00Izz H00jOE{cSD9 diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json deleted file mode 100644 index 8983e0fc1c5e..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.Development.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json deleted file mode 100644 index fbfae3faeef8..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/appsettings.json +++ /dev/null @@ -1,19 +0,0 @@ -{ -////#if (IndividualLocalAuth) -// "ConnectionStrings": { -////#if (UseLocalDB) -// "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BlazorServerWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true" -////#else -// "DefaultConnection": "DataSource=app.db" -////#endif -// }, -////#endif - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs deleted file mode 100644 index de28f359b482..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/ClaimValue.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace BlazorWasm_CSharp.Shared.Authorization -{ - public class ClaimValue - { - public ClaimValue() - { - } - - public ClaimValue(string type, string value) - { - Type = type; - Value = value; - } - - public string Type { get; set; } - public string Value { get; set; } - } -} diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs deleted file mode 100644 index c21d8b50d604..000000000000 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/Authorization/UserInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; - -namespace BlazorWasm_CSharp.Shared.Authorization -{ - public class UserInfo - { - public static readonly UserInfo Anonymous = new UserInfo(); - - public bool IsAuthenticated { get; set; } - - public string NameClaimType { get; set; } - - public string RoleClaimType { get; set; } - - public ICollection<ClaimValue> Claims { get; set; } - } -} diff --git a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs index 238385bf17e0..41cb82ac21ec 100644 --- a/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/test/BlazorWasmTemplateTest.cs @@ -1,7 +1,6 @@ // 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.Net; using System.Threading; @@ -91,64 +90,7 @@ public async Task BlazorWasmHostedTemplate_Works() } } - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task BlazorWasmHostedTemplate_IndividualAuth_Works(bool useLocalDb) - { - var project = await ProjectFactory.GetOrCreateProject("blazorhostedindividual" + (useLocalDb ? "uld" : ""), Output); - - var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "--hosted", "-au", "Individual", useLocalDb ? "-uld" : "" }); - Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); - - var serverProject = GetSubProject(project, "Server", $"{project.ProjectName}.Server"); - - var serverProjectFileContents = ReadFile(serverProject.TemplateOutputDir, $"{serverProject.ProjectName}.csproj"); - if (!useLocalDb) - { - Assert.Contains(".db", serverProjectFileContents); - } - var publishResult = await serverProject.RunDotNetPublishAsync(); - Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", serverProject, publishResult)); - - // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release - // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build - // later, while the opposite is not true. - - var buildResult = await serverProject.RunDotNetBuildAsync(); - Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", serverProject, buildResult)); - - var migrationsResult = await serverProject.RunDotNetEfCreateMigrationAsync("blazorwasm"); - Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", serverProject, migrationsResult)); - serverProject.AssertEmptyMigration("blazorwasm"); - - if (useLocalDb) - { - using var dbUpdateResult = await serverProject.RunDotNetEfUpdateDatabaseAsync(); - Assert.True(0 == dbUpdateResult.ExitCode, ErrorMessages.GetFailedProcessMessage("update database", serverProject, dbUpdateResult)); - } - - await BuildAndRunTest(project.ProjectName, serverProject, usesAuth: true); - - using var aspNetProcess = serverProject.StartPublishedProjectAsync(); - - Assert.False( - aspNetProcess.Process.HasExited, - ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", serverProject, aspNetProcess.Process)); - - await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html"); - if (BrowserFixture.IsHostAutomationSupported()) - { - aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(project.ProjectName, usesAuth: true); - } - else - { - BrowserFixture.EnforceSupportedConfigurations(); - } - } - - protected async Task BuildAndRunTest(string appName, Project project, bool usesAuth = false) + protected async Task BuildAndRunTest(string appName, Project project) { using var aspNetProcess = project.StartBuiltProjectAsync(); @@ -160,7 +102,7 @@ protected async Task BuildAndRunTest(string appName, Project project, bool usesA if (BrowserFixture.IsHostAutomationSupported()) { aspNetProcess.VisitInBrowser(Browser); - TestBasicNavigation(appName, usesAuth); + TestBasicNavigation(appName); } else { @@ -168,7 +110,7 @@ protected async Task BuildAndRunTest(string appName, Project project, bool usesA } } - private void TestBasicNavigation(string appName, bool usesAuth = false) + private void TestBasicNavigation(string appName) { // Give components.server enough time to load so that it can replace // the prerendered content before we start making assertions. @@ -191,40 +133,6 @@ private void TestBasicNavigation(string appName, bool usesAuth = false) Browser.FindElement(By.CssSelector("p+button")).Click(); Browser.Equal("Current count: 1", () => Browser.FindElement(By.CssSelector("h1 + p")).Text); - if (usesAuth) - { - Browser.FindElement(By.PartialLinkText("Log in")).Click(); - Browser.Contains("/Identity/Account/Login", () => Browser.Url); - - Browser.FindElement(By.PartialLinkText("Register as a new user")).Click(); - - var userName = $"{Guid.NewGuid()}@example.com"; - var password = $"!Test.Password1$"; - Browser.Exists(By.Name("Input.Email")); - Browser.FindElement(By.Name("Input.Email")).SendKeys(userName); - Browser.FindElement(By.Name("Input.Password")).SendKeys(password); - Browser.FindElement(By.Name("Input.ConfirmPassword")).SendKeys(password); - Browser.FindElement(By.Id("registerSubmit")).Click(); - - // We will be redirected to the RegisterConfirmation - Browser.Contains("/Identity/Account/RegisterConfirmation", () => Browser.Url); - Browser.FindElement(By.PartialLinkText("Click here to confirm your account")).Click(); - - // We will be redirected to the ConfirmEmail - Browser.Contains("/Identity/Account/ConfirmEmail", () => Browser.Url); - - // Now we can login - Browser.FindElement(By.PartialLinkText("Login")).Click(); - Browser.Exists(By.Name("Input.Email")); - Browser.FindElement(By.Name("Input.Email")).SendKeys(userName); - Browser.FindElement(By.Name("Input.Password")).SendKeys(password); - Browser.FindElement(By.Id("login-submit")).Click(); - - // Need to navigate to fetch page - Browser.Navigate().GoToUrl(new Uri(Browser.Url).GetLeftPart(UriPartial.Authority)); - Browser.Equal(appName.Trim(), () => Browser.Title.Trim()); - } - // Can navigate to the 'fetch data' page Browser.FindElement(By.PartialLinkText("Fetch data")).Click(); Browser.Contains("fetchdata", () => Browser.Url); @@ -235,15 +143,6 @@ private void TestBasicNavigation(string appName, bool usesAuth = false) Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count); } - private string ReadFile(string basePath, string path) - { - var fullPath = Path.Combine(basePath, path); - var doesExist = File.Exists(fullPath); - - Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}"); - return File.ReadAllText(Path.Combine(basePath, path)); - } - private Project GetSubProject(Project project, string projectDirectory, string projectName) { var subProjectDirectory = Path.Combine(project.TemplateOutputDir, projectDirectory); From 5f43e7a8a8e8d083e7416fb5f20cb003936c97da Mon Sep 17 00:00:00 2001 From: Daniel Roth <daroth@microsoft.com> Date: Thu, 23 Jan 2020 09:01:15 -0800 Subject: [PATCH 059/322] Update survey link for 3.2.0-preview1 (#18513) --- .../content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor index 2b7b716c201e..adb69df8e842 100644 --- a/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor +++ b/src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor @@ -4,7 +4,7 @@ <span class="text-nowrap"> Please take our - <a target="_blank" class="font-weight-bold" href="https://go.microsoft.com/fwlink/?linkid=2109206">brief survey</a> + <a target="_blank" class="font-weight-bold" href="https://go.microsoft.com/fwlink/?linkid=2116045">brief survey</a> </span> and tell us what you think. </div> From 9bdf208631be6a68663841ee58fde5536845f42b Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Fri, 24 Jan 2020 15:05:45 -0800 Subject: [PATCH 060/322] Fixup bad merge (#18570) --- src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index d3fb6f2c8a45..b5e9189a0d79 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -199,7 +199,7 @@ static string GetListeningUrl(IHost testApp) static async Task<(long size, long compressedSize)> GetBlazorAppSize() { - var testAssembly = typeof(TestApp.Startup).Assembly; + var testAssembly = typeof(TestApp.Program).Assembly; var testAssemblyLocation = new FileInfo(testAssembly.Location); var testApp = new DirectoryInfo(Path.Combine( testAssemblyLocation.Directory.FullName, From e24f73e14b17de75bfc9eded0dd3e9887727b31e Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Fri, 24 Jan 2020 16:04:11 -0800 Subject: [PATCH 061/322] Fix build warnings in MonoProxy (#18573) --- .../Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs index dfcb373afe38..eb4cf65b50a4 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs @@ -461,7 +461,7 @@ async Task GetDetails(int msg_id, int object_id, CancellationToken token, string { result = var_list }); - } catch (Exception e) { + } catch (Exception) { Debug ($"failed to parse {res.Value}"); } SendResponse(msg_id, Result.Ok(o), token); @@ -534,7 +534,7 @@ async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token }); SendResponse (msg_id, Result.Ok (o), token); } - catch (Exception exc) { + catch (Exception) { SendResponse (msg_id, res, token); } } From 24be2992dec6773a6e71839efd1cf992deba58ec Mon Sep 17 00:00:00 2001 From: Ajay Bhargav B <ajbaaska@microsoft.com> Date: Mon, 27 Jan 2020 17:54:18 -0800 Subject: [PATCH 062/322] Run Blazor E2E tests on SauceLabs (#18456) * Run Blazor E2E tests on SauceLabs * Added azure pipeline * update yml * Update meta * More changes --- .azure/pipelines/blazor-daily-tests.yml | 59 ++++ .../StandaloneApp/wwwroot/index.html | 3 +- .../AssemblyInfo.AssemblyFixtures.cs | 1 + .../ServerFixtures/AspNetSiteServerFixture.cs | 9 +- .../ServerFixtures/DevHostServerFixture.cs | 9 +- .../ServerFixtures/ServerFixture.cs | 11 +- .../ServerFixtures/StaticSiteServerFixture.cs | 9 +- .../test/E2ETest/Tests/StandaloneAppTest.cs | 7 +- .../test/E2ETest/e2eTestSettings.json | 2 +- src/Components/test/E2ETest/package.json | 9 +- src/Components/test/E2ETest/scripts/sauce.ts | 82 ++++++ src/Components/test/E2ETest/yarn.lock | 182 +++++++++++- src/Shared/E2ETesting/BrowserFixture.cs | 120 +++++++- src/Shared/E2ETesting/E2ETestOptions.cs | 6 +- src/Shared/E2ETesting/E2ETesting.props | 1 + src/Shared/E2ETesting/E2ETesting.targets | 8 + src/Shared/E2ETesting/SauceConnectServer.cs | 262 ++++++++++++++++++ src/Shared/E2ETesting/SauceOptions.cs | 36 +++ 18 files changed, 797 insertions(+), 19 deletions(-) create mode 100644 .azure/pipelines/blazor-daily-tests.yml create mode 100644 src/Components/test/E2ETest/scripts/sauce.ts create mode 100644 src/Shared/E2ETesting/SauceConnectServer.cs create mode 100644 src/Shared/E2ETesting/SauceOptions.cs diff --git a/.azure/pipelines/blazor-daily-tests.yml b/.azure/pipelines/blazor-daily-tests.yml new file mode 100644 index 000000000000..537751bfed6b --- /dev/null +++ b/.azure/pipelines/blazor-daily-tests.yml @@ -0,0 +1,59 @@ +# Uses Scheduled Triggers, which aren't supported in YAML yet. +# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=vsts&tabs=yaml#scheduled + +# Daily Tests for Blazor +# These use Sauce Labs resources, hence they run daily rather than per-commit. + +# We just need one Windows machine because all it does is trigger SauceLabs. +variables: + SAUCE_CONNECT_DOWNLOAD_ON_INSTALL: true + E2ETESTS_SauceTest: true + E2ETESTS_Sauce__TunnelIdentifier: 'blazor-e2e-sc-proxy-tunnel' + E2ETESTS_Sauce__HostName: 'sauce.local' +jobs: +- template: jobs/default-build.yml + parameters: + buildDirectory: src/Components + isTestingJob: true + agentOs: Windows + jobName: BlazorDailyTests + jobDisplayName: "Blazor Daily Tests" + afterBuild: + + # macOS/Safari + - script: 'dotnet test --filter "StandaloneAppTest"' + workingDirectory: 'src/Components/test/E2ETest' + displayName: 'Run Blazor tests - macOS/Safari' + condition: succeededOrFailed() + env: + # Secrets need to be explicitly mapped to env variables. + E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' + E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' + # Set platform/browser configuration. + E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - macOS/Safari' + E2ETESTS_Sauce__PlatformName: 'macOS 10.14' + E2ETESTS_Sauce__BrowserName: 'Safari' + # Need to explicitly set version here because some older versions don't support timeouts in Safari. + E2ETESTS_Sauce__SeleniumVersion: '3.4.0' + + # Android/Chrome + - script: 'dotnet test --filter "StandaloneAppTest"' + workingDirectory: 'src/Components/test/E2ETest' + displayName: 'Run Blazor tests - Android/Chrome' + condition: succeededOrFailed() + env: + # Secrets need to be explicitly mapped to env variables. + E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' + E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' + # Set platform/browser configuration. + E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - Android/Chrome' + E2ETESTS_Sauce__PlatformName: 'Android' + E2ETESTS_Sauce__PlatformVersion: '10.0' + E2ETESTS_Sauce__BrowserName: 'Chrome' + E2ETESTS_Sauce__DeviceName: 'Android GoogleAPI Emulator' + E2ETESTS_Sauce__DeviceOrientation: 'portrait' + E2ETESTS_Sauce__AppiumVersion: '1.9.1' + artifacts: + - name: Windows_Logs + path: ../../artifacts/log/ + publishOnError: true \ No newline at end of file diff --git a/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html b/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html index fde34bd63924..646ea2f3da09 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html +++ b/src/Components/Blazor/testassets/StandaloneApp/wwwroot/index.html @@ -2,7 +2,8 @@ <html> <head> <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width"> + <!-- Forcing the device width here so that our automated tests work consistently on mobile browsers. --> + <meta name="viewport" content="width=1024"> <title>Blazor standalone diff --git a/src/Components/test/E2ETest/Infrastructure/AssemblyInfo.AssemblyFixtures.cs b/src/Components/test/E2ETest/Infrastructure/AssemblyInfo.AssemblyFixtures.cs index 9392d18aa9d0..4f2868269a6b 100644 --- a/src/Components/test/E2ETest/Infrastructure/AssemblyInfo.AssemblyFixtures.cs +++ b/src/Components/test/E2ETest/Infrastructure/AssemblyInfo.AssemblyFixtures.cs @@ -6,3 +6,4 @@ [assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "Microsoft.AspNetCore.Components.E2ETests")] [assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))] +[assembly: AssemblyFixture(typeof(SauceConnectServer))] diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/AspNetSiteServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/AspNetSiteServerFixture.cs index 98ad897bb9a8..abb11bc748f8 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/AspNetSiteServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/AspNetSiteServerFixture.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; +using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; @@ -34,9 +35,15 @@ protected override IHost CreateWebHost() var assembly = ApplicationAssembly ?? BuildWebHostMethod.Method.DeclaringType.Assembly; var sampleSitePath = FindSampleOrTestSitePath(assembly.FullName); + var host = "127.0.0.1"; + if (E2ETestOptions.Instance.SauceTest) + { + host = E2ETestOptions.Instance.Sauce.HostName; + } + return BuildWebHostMethod(new[] { - "--urls", "http://127.0.0.1:0", + "--urls", $"http://{host}:0", "--contentroot", sampleSitePath, "--environment", Environment.ToString(), }.Concat(AdditionalArguments).ToArray()); diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/DevHostServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/DevHostServerFixture.cs index d487598539d3..d09118ef3f5d 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/DevHostServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/DevHostServerFixture.cs @@ -1,6 +1,7 @@ // 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.E2ETesting; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Http.Features; @@ -24,9 +25,15 @@ protected override IHost CreateWebHost() ContentRoot = FindSampleOrTestSitePath( typeof(TProgram).Assembly.FullName); + var host = "127.0.0.1"; + if (E2ETestOptions.Instance.SauceTest) + { + host = E2ETestOptions.Instance.Sauce.HostName; + } + var args = new List { - "--urls", "http://127.0.0.1:0", + "--urls", $"http://{host}:0", "--contentroot", ContentRoot, "--pathbase", PathBase, "--applicationpath", typeof(TProgram).Assembly.Location, diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs index 742a83f12f8f..67c164543caf 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; +using Microsoft.AspNetCore.E2ETesting; namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures { @@ -22,7 +23,15 @@ public abstract class ServerFixture : IDisposable public ServerFixture() { _rootUriInitializer = new Lazy(() => - new Uri(StartAndGetRootUri())); + { + var uri = new Uri(StartAndGetRootUri()); + if (E2ETestOptions.Instance.SauceTest) + { + uri = new UriBuilder(uri.Scheme, E2ETestOptions.Instance.Sauce.HostName, uri.Port).Uri; + } + + return uri; + }); } public abstract void Dispose(); diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/StaticSiteServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/StaticSiteServerFixture.cs index 899f165e936a..096e9315feb5 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/StaticSiteServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/StaticSiteServerFixture.cs @@ -4,6 +4,7 @@ using System; using System.IO; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; @@ -26,13 +27,19 @@ protected override IHost CreateWebHost() var sampleSitePath = FindSampleOrTestSitePath(SampleSiteName); + var host = "127.0.0.1"; + if (E2ETestOptions.Instance.SauceTest) + { + host = E2ETestOptions.Instance.Sauce.HostName; + } + return new HostBuilder() .ConfigureWebHost(webHostBuilder => webHostBuilder .UseKestrel() .UseContentRoot(sampleSitePath) .UseWebRoot(string.Empty) .UseStartup() - .UseUrls("http://127.0.0.1:0")) + .UseUrls($"http://{host}:0")) .Build(); } diff --git a/src/Components/test/E2ETest/Tests/StandaloneAppTest.cs b/src/Components/test/E2ETest/Tests/StandaloneAppTest.cs index db665d64c01a..4cc1f57cffd4 100644 --- a/src/Components/test/E2ETest/Tests/StandaloneAppTest.cs +++ b/src/Components/test/E2ETest/Tests/StandaloneAppTest.cs @@ -8,7 +8,6 @@ using OpenQA.Selenium.Support.UI; using System; using System.Linq; -using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -52,7 +51,7 @@ public void NavMenuHighlightsCurrentLocation() // Verify we start at home, with the home link highlighted Assert.Equal("Hello, world!", Browser.FindElement(mainHeaderSelector).Text); Assert.Collection(Browser.FindElements(activeNavLinksSelector), - item => Assert.Equal("Home", item.Text)); + item => Assert.Equal("Home", item.Text.Trim())); // Click on the "counter" link Browser.FindElement(By.LinkText("Counter")).Click(); @@ -60,13 +59,13 @@ public void NavMenuHighlightsCurrentLocation() // Verify we're now on the counter page, with that nav link (only) highlighted Assert.Equal("Counter", Browser.FindElement(mainHeaderSelector).Text); Assert.Collection(Browser.FindElements(activeNavLinksSelector), - item => Assert.Equal("Counter", item.Text)); + item => Assert.Equal("Counter", item.Text.Trim())); // Verify we can navigate back to home too Browser.FindElement(By.LinkText("Home")).Click(); Assert.Equal("Hello, world!", Browser.FindElement(mainHeaderSelector).Text); Assert.Collection(Browser.FindElements(activeNavLinksSelector), - item => Assert.Equal("Home", item.Text)); + item => Assert.Equal("Home", item.Text.Trim())); } [Fact] diff --git a/src/Components/test/E2ETest/e2eTestSettings.json b/src/Components/test/E2ETest/e2eTestSettings.json index 809f33f04653..1a7155db3091 100644 --- a/src/Components/test/E2ETest/e2eTestSettings.json +++ b/src/Components/test/E2ETest/e2eTestSettings.json @@ -1,4 +1,4 @@ { "DefaultWaitTimeoutInSeconds": 20, - "ScreenShotsPath": "../../screenshots" + "ScreenShotsPath": "../../screenshots", } diff --git a/src/Components/test/E2ETest/package.json b/src/Components/test/E2ETest/package.json index a84e769eb42b..26a767f77b4e 100644 --- a/src/Components/test/E2ETest/package.json +++ b/src/Components/test/E2ETest/package.json @@ -6,11 +6,18 @@ "private": true, "scripts": { "selenium-standalone": "selenium-standalone", - "prepare": "selenium-standalone install" + "prepare": "selenium-standalone install", + "sauce": "ts-node ./scripts/sauce.ts" }, "author": "", "license": "Apache-2.0", "dependencies": { + "sauce-connect-launcher": "^1.3.1", "selenium-standalone": "^6.15.4" + }, + "devDependencies": { + "@types/node": "^13.1.7", + "ts-node": "^8.6.2", + "typescript": "^3.7.5" } } diff --git a/src/Components/test/E2ETest/scripts/sauce.ts b/src/Components/test/E2ETest/scripts/sauce.ts new file mode 100644 index 000000000000..395d0c1324b8 --- /dev/null +++ b/src/Components/test/E2ETest/scripts/sauce.ts @@ -0,0 +1,82 @@ +import { EOL } from "os"; +import * as _fs from "fs"; +import { promisify } from "util"; + +// Promisify things from fs we want to use. +const fs = { + createWriteStream: _fs.createWriteStream, + exists: promisify(_fs.exists), + mkdir: promisify(_fs.mkdir), + appendFile: promisify(_fs.appendFile), + readFile: promisify(_fs.readFile), +}; + +process.on("unhandledRejection", (reason) => { + console.error(`Unhandled promise rejection: ${reason}`); + process.exit(1); +}); + +let sauceUser = null; +let sauceKey = null; +let tunnelIdentifier = null; +let hostName = null; + +for (let i = 0; i < process.argv.length; i += 1) { + switch (process.argv[i]) { + case "--sauce-user": + i += 1; + sauceUser = process.argv[i]; + break; + case "--sauce-key": + i += 1; + sauceKey = process.argv[i]; + break; + case "--sauce-tunnel": + i += 1; + tunnelIdentifier = process.argv[i]; + break; + case "--use-hostname": + i += 1; + hostName = process.argv[i]; + break; + } +} + +const HOSTSFILE_PATH = process.platform === "win32" ? `${process.env.SystemRoot}\\System32\\drivers\\etc\\hosts` : null; + +(async () => { + + if (hostName) { + // Register a custom hostname in the hosts file (requires Admin, but AzDO agents run as Admin) + // Used to work around issues in Sauce Labs. + if (process.platform !== "win32") { + throw new Error("Can't use '--use-hostname' on non-Windows platform."); + } + + try { + + console.log(`Updating Hosts file (${HOSTSFILE_PATH}) to register host name '${hostName}'`); + await fs.appendFile(HOSTSFILE_PATH, `${EOL}127.0.0.1 ${hostName}${EOL}`); + + } catch (error) { + console.log(`Unable to update hosts file at ${HOSTSFILE_PATH}. Error: ${error}`); + } + } + + + // Creates a persistent proxy tunnel using Sauce Connect. + var sauceConnectLauncher = require('sauce-connect-launcher'); + + sauceConnectLauncher({ + username: sauceUser, + accessKey: sauceKey, + tunnelIdentifier: tunnelIdentifier, + }, function (err, sauceConnectProcess) { + if (err) { + console.error(err.message); + return; + } + + console.log("Sauce Connect ready"); + }); +})(); diff --git a/src/Components/test/E2ETest/yarn.lock b/src/Components/test/E2ETest/yarn.lock index 6f2b1cc3e3dd..250aa50786f2 100644 --- a/src/Components/test/E2ETest/yarn.lock +++ b/src/Components/test/E2ETest/yarn.lock @@ -2,6 +2,23 @@ # yarn lockfile v1 +"@types/node@^13.1.7": + version "13.1.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.8.tgz#1d590429fe8187a02707720ecf38a6fe46ce294b" + integrity sha512-6XzyyNM9EKQW4HKuzbo/CkOIjn/evtCmsU+MUM1xDfJ+3/rNjBttM1NgN7AOQvN6tP1Sl1D1PIKMreTArnxM9A== + +adm-zip@~0.4.3: + version "0.4.13" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a" + integrity sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw== + +agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" @@ -12,6 +29,11 @@ ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +arg@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" + integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -24,7 +46,7 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -async@^2.6.2: +async@^2.1.2, async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -46,6 +68,11 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -61,11 +88,24 @@ bl@^2.2.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -83,6 +123,11 @@ commander@^2.19.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -106,6 +151,13 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -118,6 +170,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -133,6 +190,18 @@ end-of-stream@^1.4.1: dependencies: once "^1.4.0" +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -184,6 +253,11 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -191,6 +265,18 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -213,7 +299,23 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -inherits@^2.0.3, inherits@~2.0.3: +https-proxy-agent@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81" + integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -268,11 +370,21 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +lodash@^4.16.6: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + lodash@^4.17.11, lodash@^4.17.14: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== +make-error@^1.1.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + mime-db@1.40.0: version "1.40.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" @@ -285,6 +397,13 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.40.0" +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -317,13 +436,18 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -once@^1.4.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -417,6 +541,13 @@ request@2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +rimraf@^2.5.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -432,6 +563,17 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sauce-connect-launcher@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.3.1.tgz#31137f57b0f7176e1c0525b7fb09c6da746647cf" + integrity sha512-vIf9qDol3q2FlYzrKt0dr3kvec6LSjX2WS+/mVnAJIhqh1evSkPKCR2AzcJrnSmx9Xt9PtV0tLY7jYh0wsQi8A== + dependencies: + adm-zip "~0.4.3" + async "^2.1.2" + https-proxy-agent "^3.0.0" + lodash "^4.16.6" + rimraf "^2.5.4" + selenium-standalone@^6.15.4: version "6.16.0" resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.16.0.tgz#ffcf02665c58ff7a7472427ae819ba79c15967ac" @@ -468,6 +610,19 @@ shebang-regex@^1.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -516,6 +671,17 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +ts-node@^8.6.2: + version "8.6.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.6.2.tgz#7419a01391a818fbafa6f826a33c1a13e9464e35" + integrity sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "3.1.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -528,6 +694,11 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +typescript@^3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -578,3 +749,8 @@ yauzl@^2.10.0: dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/src/Shared/E2ETesting/BrowserFixture.cs b/src/Shared/E2ETesting/BrowserFixture.cs index 780817631863..bf8b31d29426 100644 --- a/src/Shared/E2ETesting/BrowserFixture.cs +++ b/src/Shared/E2ETesting/BrowserFixture.cs @@ -72,13 +72,24 @@ public async Task DisposeAsync() public Task<(IWebDriver, ILogs)> GetOrCreateBrowserAsync(ITestOutputHelper output, string isolationContext = "") { - if (!IsHostAutomationSupported()) + Func> createBrowserFunc; + if (E2ETestOptions.Instance.SauceTest) { - output.WriteLine($"{nameof(BrowserFixture)}: Host does not support browser automation."); - return Task.FromResult<(IWebDriver, ILogs)>(default); + createBrowserFunc = CreateSauceBrowserAsync; } + else + { + if (!IsHostAutomationSupported()) + { + output.WriteLine($"{nameof(BrowserFixture)}: Host does not support browser automation."); + return Task.FromResult<(IWebDriver, ILogs)>(default); + } - return _browsers.GetOrAdd(isolationContext, CreateBrowserAsync, output); + createBrowserFunc = CreateBrowserAsync; + } + + + return _browsers.GetOrAdd(isolationContext, createBrowserFunc, output); } public Task InitializeAsync() => Task.CompletedTask; @@ -143,5 +154,106 @@ public async Task DisposeAsync() throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive"); } + + private async Task<(IWebDriver browser, ILogs log)> CreateSauceBrowserAsync(string context, ITestOutputHelper output) + { + var sauce = E2ETestOptions.Instance.Sauce; + + if (sauce == null || + string.IsNullOrEmpty(sauce.TestName) || + string.IsNullOrEmpty(sauce.Username) || + string.IsNullOrEmpty(sauce.AccessKey) || + string.IsNullOrEmpty(sauce.TunnelIdentifier) || + string.IsNullOrEmpty(sauce.PlatformName) || + string.IsNullOrEmpty(sauce.BrowserName)) + { + throw new InvalidOperationException("Required SauceLabs environment variables not set."); + } + + var name = sauce.TestName; + if (!string.IsNullOrEmpty(context)) + { + name = $"{name} - {context}"; + } + + var capabilities = new DesiredCapabilities(); + + // Required config + capabilities.SetCapability("username", sauce.Username); + capabilities.SetCapability("accessKey", sauce.AccessKey); + capabilities.SetCapability("tunnelIdentifier", sauce.TunnelIdentifier); + capabilities.SetCapability("name", name); + + if (!string.IsNullOrEmpty(sauce.BrowserName)) + { + capabilities.SetCapability("browserName", sauce.BrowserName); + } + + if (!string.IsNullOrEmpty(sauce.PlatformVersion)) + { + capabilities.SetCapability("platformName", sauce.PlatformName); + capabilities.SetCapability("platformVersion", sauce.PlatformVersion); + } + else + { + // In some cases (like macOS), SauceLabs expects us to set "platform" instead of "platformName". + capabilities.SetCapability("platform", sauce.PlatformName); + } + + if (!string.IsNullOrEmpty(sauce.BrowserVersion)) + { + capabilities.SetCapability("browserVersion", sauce.BrowserVersion); + } + + if (!string.IsNullOrEmpty(sauce.DeviceName)) + { + capabilities.SetCapability("deviceName", sauce.DeviceName); + } + + if (!string.IsNullOrEmpty(sauce.DeviceOrientation)) + { + capabilities.SetCapability("deviceOrientation", sauce.DeviceOrientation); + } + + if (!string.IsNullOrEmpty(sauce.AppiumVersion)) + { + capabilities.SetCapability("appiumVersion", sauce.AppiumVersion); + } + + if (!string.IsNullOrEmpty(sauce.SeleniumVersion)) + { + capabilities.SetCapability("seleniumVersion", sauce.SeleniumVersion); + } + + await SauceConnectServer.StartAsync(output); + + var attempt = 0; + const int maxAttempts = 3; + do + { + try + { + // Attempt to create a new browser in SauceLabs. + var driver = new RemoteWebDriver( + new Uri("http://localhost:4445/wd/hub"), + capabilities, + TimeSpan.FromSeconds(60).Add(TimeSpan.FromSeconds(attempt * 60))); + + driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1); + var logs = new RemoteLogs(driver); + + return (driver, logs); + } + catch (Exception ex) + { + output.WriteLine($"Error initializing RemoteWebDriver: {ex.Message}"); + } + + attempt++; + + } while (attempt < maxAttempts); + + throw new InvalidOperationException("Couldn't create a SauceLabs remote driver client."); + } } } diff --git a/src/Shared/E2ETesting/E2ETestOptions.cs b/src/Shared/E2ETesting/E2ETestOptions.cs index 0b353201761e..4be16ef7799b 100644 --- a/src/Shared/E2ETesting/E2ETestOptions.cs +++ b/src/Shared/E2ETesting/E2ETestOptions.cs @@ -39,7 +39,7 @@ static E2ETestOptions() } Configuration = builder - .AddEnvironmentVariables("E2ETESTS") + .AddEnvironmentVariables("E2ETESTS_") .Build(); var instance = new E2ETestOptions(); @@ -56,5 +56,9 @@ static E2ETestOptions() public string ScreenShotsPath { get; set; } public double DefaultAfterFailureWaitTimeoutInSeconds { get; set; } = 3; + + public bool SauceTest { get; set; } + + public SauceOptions Sauce { get; set; } } } diff --git a/src/Shared/E2ETesting/E2ETesting.props b/src/Shared/E2ETesting/E2ETesting.props index e31cbd93ac22..643341106090 100644 --- a/src/Shared/E2ETesting/E2ETesting.props +++ b/src/Shared/E2ETesting/E2ETesting.props @@ -5,6 +5,7 @@ $([MSBuild]::NormalizeDirectory('$(ArtifactsTestResultsDir)','$(MSBuildProjectName)')) $([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))artifacts\tmp\selenium\ true + $([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))artifacts\tmp\sauceconnect\ true diff --git a/src/Shared/E2ETesting/E2ETesting.targets b/src/Shared/E2ETesting/E2ETesting.targets index 500d910a300b..1cb421de3bba 100644 --- a/src/Shared/E2ETesting/E2ETesting.targets +++ b/src/Shared/E2ETesting/E2ETesting.targets @@ -121,6 +121,14 @@ <_Parameter2>$(SeleniumProcessTrackingFolder) + + + + <_Parameter1>Microsoft.AspNetCore.Testing.SauceConnect.ProcessTracking + <_Parameter2>$(SauceConnectProcessTrackingFolder) + + diff --git a/src/Shared/E2ETesting/SauceConnectServer.cs b/src/Shared/E2ETesting/SauceConnectServer.cs new file mode 100644 index 000000000000..ac53b9b47231 --- /dev/null +++ b/src/Shared/E2ETesting/SauceConnectServer.cs @@ -0,0 +1,262 @@ +// 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.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.Extensions.Internal; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Microsoft.AspNetCore.E2ETesting +{ + public class SauceConnectServer : IDisposable + { + private static SemaphoreSlim _semaphore = new SemaphoreSlim(1); + + private Process _process; + private string _sentinelPath; + private Process _sentinelProcess; + private static IMessageSink _diagnosticsMessageSink; + + // 2h + private static int SauceConnectProcessTimeout = 7200; + + public SauceConnectServer(IMessageSink diagnosticsMessageSink) + { + if (Instance != null || _diagnosticsMessageSink != null) + { + throw new InvalidOperationException("Sauce connect singleton already created."); + } + + // The assembly level attribute AssemblyFixture takes care of this being being instantiated before tests run + // and disposed after tests are run, gracefully shutting down the server when possible by calling Dispose on + // the singleton. + Instance = this; + _diagnosticsMessageSink = diagnosticsMessageSink; + } + + private void Initialize( + Process process, + string sentinelPath, + Process sentinelProcess) + { + _process = process; + _sentinelPath = sentinelPath; + _sentinelProcess = sentinelProcess; + } + + internal static SauceConnectServer Instance { get; private set; } + + public static async Task StartAsync(ITestOutputHelper output) + { + try + { + await _semaphore.WaitAsync(); + if (Instance._process == null) + { + // No process was started, meaning the instance wasn't initialized. + await InitializeInstance(output); + } + } + finally + { + _semaphore.Release(); + } + } + + private static async Task InitializeInstance(ITestOutputHelper output) + { + var psi = new ProcessStartInfo + { + FileName = "npm", + Arguments = "run sauce --" + + $" --sauce-user {E2ETestOptions.Instance.Sauce.Username}" + + $" --sauce-key {E2ETestOptions.Instance.Sauce.AccessKey}" + + $" --sauce-tunnel {E2ETestOptions.Instance.Sauce.TunnelIdentifier}" + + $" --use-hostname {E2ETestOptions.Instance.Sauce.HostName}", + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + psi.FileName = "cmd"; + psi.Arguments = $"/c npm {psi.Arguments}"; + } + + // It's important that we get the folder value before we start the process to prevent + // untracked processes when the tracking folder is not correctly configure. + var trackingFolder = GetProcessTrackingFolder(); + if (!Directory.Exists(trackingFolder)) + { + throw new InvalidOperationException($"Invalid tracking folder. Set the 'SauceConnectProcessTrackingFolder' MSBuild property to a valid folder."); + } + + Process process = null; + Process sentinel = null; + string pidFilePath = null; + try + { + process = Process.Start(psi); + pidFilePath = await WriteTrackingFileAsync(output, trackingFolder, process); + sentinel = StartSentinelProcess(process, pidFilePath, SauceConnectProcessTimeout); + } + catch + { + ProcessCleanup(process, pidFilePath); + ProcessCleanup(sentinel, pidFilePath: null); + throw; + } + + // Log output for sauce connect process. + // This is for the case where the server fails to launch. + var logOutput = new BlockingCollection(); + + process.OutputDataReceived += LogOutput; + process.ErrorDataReceived += LogOutput; + + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + // The Sauce connect server has to be up for the entirety of the tests and is only shutdown when the application (i.e. the test) exits. + AppDomain.CurrentDomain.ProcessExit += (sender, args) => ProcessCleanup(process, pidFilePath); + + // Log + void LogOutput(object sender, DataReceivedEventArgs e) + { + logOutput.TryAdd(e.Data); + + // We avoid logging on the output here because it is unreliable. We can only log in the diagnostics sink. + lock (_diagnosticsMessageSink) + { + _diagnosticsMessageSink.OnMessage(new DiagnosticMessage(e.Data)); + } + } + + var uri = new UriBuilder("http", E2ETestOptions.Instance.Sauce.HostName, 4445).Uri; + var httpClient = new HttpClient + { + Timeout = TimeSpan.FromSeconds(1), + }; + + var retries = 0; + do + { + await Task.Delay(1000); + try + { + var response = await httpClient.GetAsync(uri); + if (response.StatusCode == HttpStatusCode.OK) + { + output = null; + Instance.Initialize(process, pidFilePath, sentinel); + return; + } + } + catch (OperationCanceledException) + { + } + catch (HttpRequestException) + { + } + + retries++; + } while (retries < 30); + + // Make output null so that we stop logging to it. + output = null; + logOutput.CompleteAdding(); + var exitCodeString = process.HasExited ? process.ExitCode.ToString() : "Process has not yet exited."; + var message = $@"Failed to launch the server. +ExitCode: {exitCodeString} +Captured output lines: +{string.Join(Environment.NewLine, logOutput.GetConsumingEnumerable())}."; + + // If we got here, we couldn't launch Sauce connect or get it to respond. So shut it down. + ProcessCleanup(process, pidFilePath); + throw new InvalidOperationException(message); + } + + private static Process StartSentinelProcess(Process process, string sentinelFile, int timeout) + { + // This sentinel process will start and will kill any rouge sauce connect server that wasn't torn down via normal means. + var psi = new ProcessStartInfo + { + FileName = "powershell", + Arguments = $"-NoProfile -NonInteractive -Command \"Start-Sleep {timeout}; " + + $"if(Test-Path {sentinelFile}){{ " + + $"Write-Output 'Stopping process {process.Id}'; Stop-Process {process.Id}; }}" + + $"else{{ Write-Output 'Sentinel file {sentinelFile} not found.'}}", + }; + + return Process.Start(psi); + } + + private static void ProcessCleanup(Process process, string pidFilePath) + { + try + { + if (process?.HasExited == false) + { + try + { + process?.KillTree(TimeSpan.FromSeconds(10)); + process?.Dispose(); + } + catch + { + // Ignore errors here since we can't do anything + } + } + if (pidFilePath != null && File.Exists(pidFilePath)) + { + File.Delete(pidFilePath); + } + } + catch + { + // Ignore errors here since we can't do anything + } + } + + private static async Task WriteTrackingFileAsync(ITestOutputHelper output, string trackingFolder, Process process) + { + var pidFile = Path.Combine(trackingFolder, $"{process.Id}.{Guid.NewGuid()}.pid"); + for (var i = 0; i < 3; i++) + { + try + { + await File.WriteAllTextAsync(pidFile, process.Id.ToString()); + return pidFile; + } + catch + { + output.WriteLine($"Can't write file to process tracking folder: {trackingFolder}"); + } + } + + throw new InvalidOperationException($"Failed to write file for process {process.Id}"); + } + + private static string GetProcessTrackingFolder() => + typeof(SauceConnectServer).Assembly + .GetCustomAttributes() + .Single(a => a.Key == "Microsoft.AspNetCore.Testing.SauceConnect.ProcessTracking").Value; + + public void Dispose() + { + ProcessCleanup(_process, _sentinelPath); + ProcessCleanup(_sentinelProcess, pidFilePath: null); + } + } +} diff --git a/src/Shared/E2ETesting/SauceOptions.cs b/src/Shared/E2ETesting/SauceOptions.cs new file mode 100644 index 000000000000..b8bb22ec8c51 --- /dev/null +++ b/src/Shared/E2ETesting/SauceOptions.cs @@ -0,0 +1,36 @@ +// 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.E2ETesting +{ + public class SauceOptions + { + public string Username { get; set; } + + public string AccessKey { get; set; } + + public string TunnelIdentifier { get; set; } + + public string HostName { get; set; } + + public string TestName { get; set; } + + public bool IsRealDevice { get; set; } + + public string PlatformName { get; set; } + + public string PlatformVersion { get; set; } + + public string BrowserName { get; set; } + + public string BrowserVersion { get; set; } + + public string DeviceName { get; set; } + + public string DeviceOrientation { get; set; } + + public string AppiumVersion { get; set; } + + public string SeleniumVersion { get; set; } + } +} From bb1b2c4bf29ae69604aef120d1c418566b568db8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 28 Jan 2020 09:08:57 -0800 Subject: [PATCH 063/322] Use scenario name for measurements and metadata (#18609) --- .../benchmarkapps/Wasm.Performance/Driver/Program.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index b5e9189a0d79..8d588b643041 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -75,10 +75,11 @@ private static void FormatAsBenchmarksOutput(List results, (lon var output = new BenchmarkOutput(); foreach (var result in results) { + var scenarioName = result.Descriptor.Name; output.Metadata.Add(new BenchmarkMetadata { Source = "BlazorWasm", - Name = result.Descriptor.Name, + Name = scenarioName, ShortDescription = result.Name, LongDescription = result.Descriptor.Description, Format = "n2" @@ -87,7 +88,7 @@ private static void FormatAsBenchmarksOutput(List results, (lon output.Measurements.Add(new BenchmarkMeasurement { Timestamp = DateTime.UtcNow, - Name = result.Name, + Name = scenarioName, Value = result.Duration, }); } From bbafecc0535e1de3264845e51ea8b3d18eb3ca61 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 28 Jan 2020 13:18:31 -0800 Subject: [PATCH 064/322] Update Web.JS scripts (#18635) --- src/Components/Web.JS/dist/Release/blazor.server.js | 13 +++---------- .../Web.JS/dist/Release/blazor.webassembly.js | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index 400db6164b83..36050055b123 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -1,22 +1,15 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=51)}([function(e,t,n){"use strict";var r;n.d(t,"a",function(){return r}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(r||(r={}))},function(e,t,n){"use strict";n.d(t,"a",function(){return a}),n.d(t,"c",function(){return u}),n.d(t,"f",function(){return c}),n.d(t,"g",function(){return l}),n.d(t,"h",function(){return f}),n.d(t,"e",function(){return h}),n.d(t,"d",function(){return p}),n.d(t,"b",function(){return d});var r=n(0),o=n(6),i=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},s=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=n(3),s=n(4),a=n(45),u=n(0),c=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=function(e){function t(t){var n=e.call(this)||this;return n.logger=t,n}return c(t,e),t.prototype.send=function(e){var t=this;return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?new Promise(function(n,r){var o=new XMLHttpRequest;o.open(e.method,e.url,!0),o.withCredentials=!0,o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Content-Type","text/plain;charset=UTF-8");var a=e.headers;a&&Object.keys(a).forEach(function(e){o.setRequestHeader(e,a[e])}),e.responseType&&(o.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=function(){o.abort(),r(new i.a)}),e.timeout&&(o.timeout=e.timeout),o.onload=function(){e.abortSignal&&(e.abortSignal.onabort=null),o.status>=200&&o.status<300?n(new s.b(o.status,o.statusText,o.response||o.responseText)):r(new i.b(o.statusText,o.status))},o.onerror=function(){t.logger.log(u.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i.b(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(u.a.Warning,"Timeout from HTTP request."),r(new i.c)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(s.a),f=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),h=function(e){function t(t){var n=e.call(this)||this;return"undefined"!=typeof XMLHttpRequest?n.httpClient=new l(t):n.httpClient=new a.a(t),n}return f(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(s.a),p=n(46);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(o||(o={}));var d,g=n(1),y=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}})})},e.prototype.constructTransport=function(e){switch(e){case E.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new M(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket);case E.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new D(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource);case E.LongPolling:return new R(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1);default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=E[e.transport];if(null==r)return this.logger.log(u.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it was disabled by the client."),new Error("'"+E[r]+"' is disabled by the client.");if(!(e.transferFormats.map(function(e){return S[e]}).indexOf(n)>=0))return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it does not support the requested transfer format '"+S[n]+"'."),new Error("'"+E[r]+"' does not support "+S[n]+".");if(r===E.WebSockets&&!this.options.WebSocket||r===E.ServerSentEvents&&!this.options.EventSource)return this.logger.log(u.a.Debug,"Skipping transport '"+E[r]+"' because it is not supported in your environment.'"),new Error("'"+E[r]+"' is not supported in your environment.");this.logger.log(u.a.Debug,"Selecting transport '"+E[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){if(this.logger.log(u.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState)if("Connecting "!==this.connectionState){if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(u.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(u.a.Information,"Connection disconnected."),this.connectionId=void 0,this.connectionState="Disconnected",this.onclose&&this.connectionStarted){this.connectionStarted=!1;try{this.onclose(e)}catch(t){this.logger.log(u.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(u.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection hasn't yet left the in the connecting state.");else this.logger.log(u.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!g.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(u.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var q=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new Y,this.transportResult=new Y,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new Y),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return B(this,void 0,void 0,function(){var t,n,r;return U(this,function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new Y,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}})})},e.concatBuffers=function(e){for(var t=e.map(function(e){return e.byteLength}).reduce(function(e,t){return e+t}),n=new Uint8Array(t),r=0,o=0,i=e;o=0,"must have a non-negative type"),o(s,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),s=r.allocUnsafe(1);return s.writeInt8(e,0),o.append(s),o.append(n(t)),o}),this.registerDecoder(e,s),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:s.encoder,decoder:s.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:a.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function a(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var s=c(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var s=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=s}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(20),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=s),i(o,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function s(e){t.push(e)}function a(e,t,n,r){var o=c();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),s=o.invokeDotNetFromJS(e,t,n,i);return s?f(s):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var s=o++,a=new Promise(function(e,t){n[s]={resolve:e,reject:t}});try{var u=JSON.stringify(i,g);c().beginInvokeDotNetFromJS(s,e,t,r,u)}catch(e){l(s,!1,e)}return a}function c(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=s,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=n(3),a=n(4),s=n(43),c=n(0),u=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=function(e){function t(t){var n=e.call(this)||this;return n.logger=t,n}return u(t,e),t.prototype.send=function(e){var t=this;return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?new Promise(function(n,r){var o=new XMLHttpRequest;o.open(e.method,e.url,!0),o.withCredentials=!0,o.setRequestHeader("X-Requested-With","XMLHttpRequest"),o.setRequestHeader("Content-Type","text/plain;charset=UTF-8");var s=e.headers;s&&Object.keys(s).forEach(function(e){o.setRequestHeader(e,s[e])}),e.responseType&&(o.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=function(){o.abort(),r(new i.a)}),e.timeout&&(o.timeout=e.timeout),o.onload=function(){e.abortSignal&&(e.abortSignal.onabort=null),o.status>=200&&o.status<300?n(new a.b(o.status,o.statusText,o.response||o.responseText)):r(new i.b(o.statusText,o.status))},o.onerror=function(){t.logger.log(c.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i.b(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(c.a.Warning,"Timeout from HTTP request."),r(new i.c)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(a.a),f=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),h=function(e){function t(t){var n=e.call(this)||this;return"undefined"!=typeof XMLHttpRequest?n.httpClient=new l(t):n.httpClient=new s.a(t),n}return f(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new i.a):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(a.a),p=n(44);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(o||(o={}));var d,g=n(1),y=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}})})},e.prototype.constructTransport=function(e){switch(e){case E.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new A(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket);case E.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new O(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource);case E.LongPolling:return new x(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1);default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=E[e.transport];if(null==r)return this.logger.log(c.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it was disabled by the client."),new Error("'"+E[r]+"' is disabled by the client.");if(!(e.transferFormats.map(function(e){return S[e]}).indexOf(n)>=0))return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it does not support the requested transfer format '"+S[n]+"'."),new Error("'"+E[r]+"' does not support "+S[n]+".");if(r===E.WebSockets&&!this.options.WebSocket||r===E.ServerSentEvents&&!this.options.EventSource)return this.logger.log(c.a.Debug,"Skipping transport '"+E[r]+"' because it is not supported in your environment.'"),new Error("'"+E[r]+"' is not supported in your environment.");this.logger.log(c.a.Debug,"Selecting transport '"+E[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){if(this.logger.log(c.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState)if("Connecting "!==this.connectionState){if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(c.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(c.a.Information,"Connection disconnected."),this.connectionId=void 0,this.connectionState="Disconnected",this.onclose&&this.connectionStarted){this.connectionStarted=!1;try{this.onclose(e)}catch(t){this.logger.log(c.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(c.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection hasn't yet left the in the connecting state.");else this.logger.log(c.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!g.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(c.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var q=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new W,this.transportResult=new W,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new W),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return B(this,void 0,void 0,function(){var t,n,r;return j(this,function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new W,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}})})},e.concatBuffers=function(e){for(var t=e.map(function(e){return e.byteLength}).reduce(function(e,t){return e+t}),n=new Uint8Array(t),r=0,o=0,i=e;o * @license MIT */ -var r=n(55),o=n(56),i=n(57);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,s=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(o){var l=-1;for(i=n;ia&&(n=a-u),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;s>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function C(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],s=e[o+2],128==(192&i)&&128==(192&s)&&(u=(15&c)<<12|(63&i)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],s=e[o+2],a=e[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=I)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),s=(n>>>=0)-(t>>>=0),a=Math.min(i,s),c=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var I=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function D(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function O(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||A(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||A(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||A(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||A(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||A(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||A(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||A(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||A(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||A(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||A(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=0,s=1,a=0;for(this[t]=255&e;++i>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=n-1,s=1,a=0;for(this[t+i]=255&e;--i>=0&&(s*=256);)e<0&&0===a&&0!==this[t+i+1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(j,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(37))},function(e,t,n){var r=n(62),o=n(36),i=n(13).Buffer;function s(e){if(!(this instanceof s))return new s(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else this.append(e);r.call(this)}o.inherits(s,r),s.prototype._offset=function(e){var t,n=0,r=0;if(0===e)return[0,0];for(;rthis.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,s,a=!!e,u=this._offset(n),c=r-n,l=c,f=a&&t||0,h=u[1];if(0===n&&r==this.length){if(!a)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(s=0;s(o=this._bufs[s].length-h))){this._bufs[s].copy(e,f,h,h+l);break}this._bufs[s].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},s.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new s(o)},s.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},s.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},s.prototype.duplicate=function(){for(var e=0,t=new s;e1)for(var n=1;n0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,c=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,c/=2,n/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;is&&(n=s-c),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function _(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function I(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:u>223?3:u>191?2:1;if(o+f<=n)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(i=e[o+1]))&&(c=(31&u)<<6|63&i)>127&&(l=c);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(c=(15&u)<<12|(63&i)<<6|63&a)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(c=(15&u)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return x(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return _(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},c.prototype.equals=function(e){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===c.compare(this,e)},c.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},c.prototype.compare=function(e,t,n,r,o){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),u=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function O(e,t,n,r,o,i){if(!c.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function M(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function A(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||A(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function j(e,t,n,r,i){return i||A(e,0,n,8),o.write(e,t,n,r,52,8),n+8}c.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},c.prototype.readUInt8=function(e,t){return t||D(e,1,this.length),this[e]},c.prototype.readUInt16LE=function(e,t){return t||D(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUInt16BE=function(e,t){return t||D(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUInt32LE=function(e,t){return t||D(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUInt32BE=function(e,t){return t||D(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},c.prototype.readInt8=function(e,t){return t||D(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},c.prototype.readInt16LE=function(e,t){t||D(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(e,t){t||D(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(e,t){return t||D(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return t||D(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return t||D(e,4,this.length),o.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return t||D(e,8,this.length),o.read(this,e,!1,52,8)},c.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||O(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},c.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,255,0),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},c.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},c.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},c.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);O(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},c.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,1,127,-128),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},c.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},c.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},c.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||O(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},c.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},c.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},c.prototype.writeDoubleLE=function(e,t,n){return j(this,e,t,!0,n)},c.prototype.writeDoubleBE=function(e,t,n){return j(this,e,t,!1,n)},c.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!c.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(9))},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}()},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){function e(){}return e.write=function(t){return""+t+e.RecordSeparator},e.parse=function(t){if(t[t.length-1]!==e.RecordSeparator)throw new Error("Message is incomplete.");var n=t.split(e.RecordSeparator);return n.pop(),n},e.RecordSeparatorCode=30,e.RecordSeparator=String.fromCharCode(e.RecordSeparatorCode),e}()},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r=n(23),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(21);i.inherits=n(15);var a=n(36),s=n(41);i.inherits(f,a);for(var c=o(s.prototype),u=0;u=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(u(i)&&u(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(c(i))throw new Error("Not implemented: moving existing logical children");var a=u(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=c,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return u(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=u,t.permuteLogicalChildren=function(e,t){var n=u(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=c(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(t.LogLevel||(t.LogLevel={}))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t,n,r){var o=u();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,g),a=o.invokeDotNetFromJS(e,t,n,i);return a?f(a):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function c(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var a=o++,s=new Promise(function(e,t){n[a]={resolve:e,reject:t}});try{var c=JSON.stringify(i,g);u().beginInvokeDotNetFromJS(a,e,t,r,c)}catch(e){l(a,!1,e)}return s}function u(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function h(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=a,e.invokeMethod=function(e,t){for(var n=[],r=2;r1)for(var n=1;nthis.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,c=this._offset(n),u=r-n,l=u,f=s&&t||0,h=c[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;e0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),c=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=c),l(r,e,r.depth)}function c(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function u(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&C(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(C(n)){var c=n.name?": "+n.name:"";return e.stylize("[Function"+c+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var u,w="",_=!1,I=["{","}"];(p(n)&&(_=!0,I=["[","]"]),C(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||_&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),u=_?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(u,w,I)):I[0]+w+I[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,c;if((c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(s=e.stylize("[Setter]","special")),k(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(c.value)<0?(s=g(n)?l(e,c.value,null):l(e,c.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),b(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===_(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===_(e)}function S(e){return w(e)&&("[object Error]"===_(e)||e instanceof Error)}function C(e){return"function"==typeof e}function _(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=C,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(54);var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":"),[e.getDate(),T[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(55),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function x(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):T(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function _(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(I,e):I(e))}function I(e){p("emit readable"),e.emit("readable"),R(e)}function T(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=u.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function O(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function M(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?O(this):_(this),null;if(0===(e=C(e,t))&&t.ended)return 0===t.length&&O(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?D(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&O(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function u(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,R(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==M(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&a.length>o&&!a.warned){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,s=c,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=o[e];if(void 0===c)return!1;if("function"==typeof c)i(c,this,t);else{var u=c.length,l=d(c,u);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(37).EventEmitter},function(e,t,n){"use strict";var r=n(23);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(61).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=u,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(23);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var s,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var u=n(21);u.inherits=n(15);var l={deprecate:n(64)},f=n(38),h=n(14).Buffer,p=o.Uint8Array||function(){};var d,g=n(39);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,u=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(_,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),_(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?c(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function b(e){if(s=s||n(10),!(d.call(b,this)||this instanceof s))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),_(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,c=!0;n;)o[s]=n,n.isBuf||(c=!1),n=n.next,s+=1;o.allBuffers=c,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var u=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:u.length,u,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),_(e,t)})}function _(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(C,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}u.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,_(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(20),n(62).setImmediate,n(9))},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(21);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length=200&&c.statusCode<300?r(new a.b(c.statusCode,c.statusMessage||"",u)):o(new i.b(c.statusMessage||"",c.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(a.a)}).call(this,n(6).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(8),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var a=new Uint8Array(t);if(-1===(c=a.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var s=c+1;n=String.fromCharCode.apply(null,a.slice(0,s)),i=a.byteLength>s?a.slice(s).buffer:null}else{var c,u=t;if(-1===(c=u.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=c+1;n=u.substring(0,s),i=u.length>s?u.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(6).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a},a=this&&this.__spread||function(){for(var e=[],t=0;t0?r-4:r,f=0;f>16&255,s[c++]=t>>8&255,s[c++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[c++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[c++]=t>>8&255,s[c++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;as?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,c=a.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,c=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-u;else{if(i===c)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=u}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,c,u=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-a))<1&&(a--,c*=2),(t+=a+f>=1?h/c:h*Math.pow(2,1-f))*c>=2&&(a++,c/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*c-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<0;e[n+p]=255&a,p+=d,a/=256,u-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ -var r=n(52),o=n(53),i=n(54);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,s=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(o){var l=-1;for(i=n;ia&&(n=a-u),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;s>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function C(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],s=e[o+2],128==(192&i)&&128==(192&s)&&(u=(15&c)<<12|(63&i)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],s=e[o+2],a=e[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=I)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),s=(n>>>=0)-(t>>>=0),a=Math.min(i,s),c=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var I=4096;function k(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function D(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function O(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function B(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||A(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||A(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||A(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||A(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||A(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||A(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||A(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||A(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||A(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||A(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||A(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||A(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||A(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||D(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=0,s=1,a=0;for(this[t]=255&e;++i>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);D(this,e,t,n,o-1,-o)}var i=n-1,s=1,a=0;for(this[t+i]=255&e;--i>=0&&(s*=256);)e<0&&0===a&&0!==this[t+i+1]&&(a=1),this[t+i]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||D(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(j,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(12))},function(e,t,n){(function(e){var r=Object.getOwnPropertyDescriptors||function(e){for(var t=Object.keys(e),n={},r=0;r=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),u=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=u),l(r,e,r.depth)}function u(e,t){var n=a.styles[t];return n?"["+a.colors[n][0]+"m"+e+"["+a.colors[n][1]+"m":e}function c(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&_(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var s=Object.keys(n),a=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(n)),S(n)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(n);if(0===s.length){if(_(n)){var u=n.name?": "+n.name:"";return e.stylize("[Function"+u+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var c,w="",T=!1,C=["{","}"];(p(n)&&(T=!0,C=["[","]"]),_(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==s.length||T&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),c=T?function(e,t,n,r,o){for(var i=[],s=0,a=t.length;s=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(c,w,C)):C[0]+w+C[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var s,a,u;if((u=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?a=u.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):u.set&&(a=e.stylize("[Setter]","special")),k(r,o)||(s="["+o+"]"),a||(e.seen.indexOf(u.value)<0?(a=g(n)?l(e,u.value,null):l(e,u.value,n-1)).indexOf("\n")>-1&&(a=i?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n")):a=e.stylize("[Circular]","special")),b(s)){if(i&&o.match(/^\d+$/))return a;(s=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===T(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===T(e)}function S(e){return w(e)&&("[object Error]"===T(e)||e instanceof Error)}function _(e){return"function"==typeof e}function T(e){return Object.prototype.toString.call(e)}function C(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!s[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;s[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else s[n]=function(){};return s[n]},t.inspect=a,a.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},a.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=_,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(60);var I=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function k(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[C(e.getHours()),C(e.getMinutes()),C(e.getSeconds())].join(":"),[e.getDate(),I[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(61),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var P="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function R(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(P&&e[P]){var t;if("function"!=typeof(t=e[P]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,P,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?s.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,s,t,!0):s.ended?e.emit("error",new Error("stream.push() after EOF")):(s.reading=!1,s.decoder&&!n?(t=s.decoder.write(t),s.objectMode||0!==t.length?E(e,s,t,!1):I(e,s)):E(e,s,t,!1))):r||(s.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function T(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(C,e):C(e))}function C(e){p("emit readable"),e.emit("readable"),x(e)}function I(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(s===i.length?o+=i:o+=i.slice(0,e),0===(e-=s)){s===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(s));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,s=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,s),0===(e-=s)){s===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(s));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function D(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(O,t,e))}function O(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function L(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?D(this):T(this),null;if(0===(e=_(e,t))&&t.ended)return 0===t.length&&D(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?A(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&D(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function c(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",c),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(u):n.once("end",u),e.on("unpipe",c);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,x(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==L(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===a(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?s(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&s.length>o&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=s.length,a=u,console&&console.warn&&console.warn(a)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var u=o[e];if(void 0===u)return!1;if("function"==typeof u)i(u,this,t);else{var c=u.length,l=d(u,c);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){s=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},a.prototype.listeners=function(e){return h(this,e,!0)},a.prototype.rawListeners=function(e){return h(this,e,!1)},a.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},a.prototype.listenerCount=p,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(39).EventEmitter},function(e,t,n){"use strict";var r=n(22);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return i||s?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var r=n(67).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";(function(t,r,o){var i=n(22);function s(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var a,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var c=n(19);c.inherits=n(14);var l={deprecate:n(70)},f=n(40),h=n(13).Buffer,p=o.Uint8Array||function(){};var d,g=n(41);function y(){}function v(e,t){a=a||n(8),e=e||{};var r=t instanceof a;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(T,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),T(e,t))}(e,n,r,t,o);else{var s=S(n);s||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?u(w,e,n,s,o):w(e,n,s,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new s(this)}function b(e){if(a=a||n(8),!(d.call(b,this)||this instanceof a))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,s){t.writelen=r,t.writecb=s,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var a=0,u=!0;n;)o[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;o.allBuffers=u,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new s(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:c.length,c,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function _(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),T(e,t)})}function T(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(_,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,s=!1,a=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return a&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(a||function(e,t,n,r){var o=!0,s=!1;return null===n?s=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),i.nextTick(r,s),o=!1),o}(this,o,e,n))&&(o.pendingcb++,s=function(e,t,n,r,o,i){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==s&&(n=!0,o="buffer",r=s)}var a=t.objectMode?1:r.length;t.length+=a;var u=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(23),n(68).setImmediate,n(12))},function(e,t,n){"use strict";e.exports=s;var r=n(8),o=n(19);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length=200&&u.statusCode<300?r(new s.b(u.statusCode,u.statusMessage||"",c)):o(new i.b(u.statusMessage||"",u.statusCode||0))});t.abortSignal&&(t.abortSignal.onabort=function(){f.abort(),o(new i.a)})})},n.prototype.getCookieString=function(e){return this.cookieJar.getCookieString(e)},n}(s.a)}).call(this,n(35).Buffer)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return i});var r=n(7),o=n(1),i=function(){function t(){}return t.prototype.writeHandshakeRequest=function(e){return r.a.write(JSON.stringify(e))},t.prototype.parseHandshakeResponse=function(t){var n,i;if(Object(o.g)(t)||void 0!==e&&t instanceof e){var s=new Uint8Array(t);if(-1===(u=s.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var a=u+1;n=String.fromCharCode.apply(null,s.slice(0,a)),i=s.byteLength>a?s.slice(a).buffer:null}else{var u,c=t;if(-1===(u=c.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");a=u+1;n=c.substring(0,a),i=c.length>a?c.substring(a):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(35).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)s.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return s},s=this&&this.__spread||function(){for(var e=[],t=0;t0?r-4:r,f=0;f>16&255,a[u++]=t>>8&255,a[u++]=255&t;2===s&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,a[u++]=255&t);1===s&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,a[u++]=t>>8&255,a[u++]=255&t);return a},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],s=0,a=n-o;sa?a:s+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,s=[],a=t;a>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,s,a=8*o-r-1,u=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=a;l>0;i=256*i+e[t+f],f+=h,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,r),i-=c}return(p?-1:1)*s*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var s,a,u,c=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),(t+=s+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(s++,u/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*u-1)*Math.pow(2,o),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;e[n+p]=255&a,p+=d,a/=256,o-=8);for(s=s<0;e[n+p]=255&s,p+=d,s/=256,c-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=c(e),r=n[0],s=n[1],a=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,s)),u=0,l=s>0?r-4:r,f=0;f>16&255,a[u++]=t>>8&255,a[u++]=255&t;2===s&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,a[u++]=255&t);1===s&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,a[u++]=t>>8&255,a[u++]=255&t);return a},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],s=0,a=n-o;sa?a:s+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,s=[],a=t;a>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,s,a=8*o-r-1,u=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=a;l>0;i=256*i+e[t+f],f+=h,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,r),i-=c}return(p?-1:1)*s*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var s,a,u,c=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),(t+=s+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(s++,u/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*u-1)*Math.pow(2,o),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;e[n+p]=255&a,p+=d,a/=256,o-=8);for(s=s<0;e[n+p]=255&s,p+=d,s/=256,c-=8);e[n+p-d]|=128*g}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";(function(t){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o=0;c--)if(l[c]!==f[c])return!1;for(c=l.length-1;c>=0;c--)if(u=l[c],!b(e[u],t[u],n,r))return!1;return!0}(e,t,n,s))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var s="string"==typeof r,a=!e&&o&&!n;if((!e&&i.isError(o)&&s&&w(o,n)||a)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),s=o.indexOf("\n"+i);if(s>=0){var a=o.indexOf("\n",s+1);o=o.substring(a+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)s.call(e,n)&&t.push(n);return t}}).call(this,n(37))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:s}catch(e){r=s}}();var u,c=[],l=!1,f=-1;function h(){l&&u&&(l=!1,u.length?c=u.concat(c):f=-1,c.length&&p())}function p(){if(!l){var e=a(h);l=!0;for(var t=c.length;t;){for(u=c,c=[];++f1)for(var n=1;n0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,n=i,o=a,t.copy(n,o),a+=s.data.length,s=s.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(20),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=s),i(o,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(69),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(12))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,s,a,u=1,c={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(s="setImmediate$"+Math.random()+"$",a=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(s)&&d(+t.data.slice(s.length))},e.addEventListener?e.addEventListener("message",a,!1):e.attachEvent("onmessage",a),r=function(t){e.postMessage(s+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=u,e.exports.encoder=a},function(e,t,n){(t=e.exports=n(38)).Stream=t,t.Readable=t,t.Writable=n(43),t.Duplex=n(8),t.Transform=n(44),t.PassThrough=n(73)},function(e,t,n){"use strict";e.exports=i;var r=n(44),o=n(19);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(14),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(21);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(36).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var s=e.readUInt32BE(t+0),a=e.readUInt32BE(t+4);return(4294967296*s+a)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),s(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),s(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),a(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return u(e,r,1);case 213:return u(e,r,2);case 214:return u(e,r,4);case 215:return u(e,r,8);case 216:return u(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?c(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?c(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?c(e,r,l,i,6):null}if(144==(240&h))return s(e,r,i=15&h,1);if(128==(240&h))return a(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function s(e,t,r,o){var s,a=[],u=0;for(t+=o,s=0;si)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function a(u,c){var l,f,h;if(void 0===u)throw new Error("undefined is not encodable in msgpack!");if(null===u)(l=r.allocUnsafe(1))[0]=192;else if(!0===u)(l=r.allocUnsafe(1))[0]=195;else if(!1===u)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof u)(f=r.byteLength(u))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(u,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(u,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(u,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(u,5));else if(u&&(u.readUInt32LE||u instanceof Uint8Array))u instanceof Uint8Array&&(u=r.from(u)),u.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=u.length):u.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(u.length,1)),l=o([l,u]);else if(Array.isArray(u))u.length<16?(l=r.allocUnsafe(1))[0]=144|u.length:u.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(u.length,1)),l=u.reduce(function(e,t){return e.append(a(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof u.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),s=1e6*(n-1e3*i);if(s||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var a=4*s,u=i/Math.pow(2,32),c=a+u&4294967295,l=4294967295&i;t.writeInt32BE(c,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(u);if("object"==typeof u)l=function(t){var n,i,s=-1,a=[];for(n=0;n>8),a.push(255&s)):(a.push(201),a.push(s>>24),a.push(s>>16&255),a.push(s>>8&255),a.push(255&s));return o().append(r.from(a)).append(i)}(u)||function(e){var t,n,i=[],s=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++s,i.push(a(t,!0)),i.push(a(e[t],!0)));s<16?(n=r.allocUnsafe(1))[0]=128|s:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(s,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(u);else if("number"==typeof u){if((h=u)!==Math.floor(h))return s(u,t);if(u>=0)if(u<128)(l=r.allocUnsafe(1))[0]=u;else if(u<256)(l=r.allocUnsafe(2))[0]=204,l[1]=u;else if(u<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(u,1);else if(u<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(u,1);else{if(!(u<=9007199254740991))return s(u,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,u)}else if(u>=-32)(l=r.allocUnsafe(1))[0]=256+u;else if(u>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(u,1);else if(u>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(u,1);else if(u>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(u,1);else{if(!(u>=-9007199254740991))return s(u,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var s=1,a=t+7;a>=t;a--){var u=(255^e[a])+s;e[a]=255&u,s=u>>8}}(l,1,u)}}}if(!l)throw new Error("not implemented yet");return c?l:l.slice()}return a}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId?this.fatalError?(this.logger.log(a.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(a.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(a.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new s.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(a.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(a.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(78),o=Math.pow(2,32),i=Math.pow(2,21)-1,s=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new a(e),this.editReader=new u(e,t),this.frameReader=new c(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=s;var a=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(15),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(s,a)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=(o=s.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=s},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(20),o=n(9),i=n(2),s=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+s))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+s):n.subarray(o+i,o+i+s)),o=o+i+s}return t},e}();var a=new Uint8Array([145,i.MessageType.Ping]),u=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],a=0,u=s.parse(e);a=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return s.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return s.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return s.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return s.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return s.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return c}),n.d(t,"MessagePackHubProtocol",function(){return u});var c="3.1.1-dev"}]); \ No newline at end of file +function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(c=l[u],!b(e[c],t[c],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(9))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){e.exports=n(10)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t){},function(e,t,n){"use strict";var r=n(14).Buffer,o=n(60);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){var r=n(6),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(9))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,c=1,u={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=c,e.exports.encoder=s},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(10),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),o=n(21);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(15),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(22);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(34).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:throw new Error("map too big to decode in JS");case 212:return c(e,r,1);case 213:return c(e,r,2);case 214:return c(e,r,4);case 215:return c(e,r,8);case 216:return c(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?u(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?u(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?u(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],c=0;for(t+=o,a=0;ai)&&((n=r.allocUnsafe(9))[0]=203,n.writeDoubleBE(e,1)),n}e.exports=function(e,t,n,i){function s(c,u){var l,f,h;if(void 0===c)throw new Error("undefined is not encodable in msgpack!");if(null===c)(l=r.allocUnsafe(1))[0]=192;else if(!0===c)(l=r.allocUnsafe(1))[0]=195;else if(!1===c)(l=r.allocUnsafe(1))[0]=194;else if("string"==typeof c)(f=r.byteLength(c))<32?((l=r.allocUnsafe(1+f))[0]=160|f,f>0&&l.write(c,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(c,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(c,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(c,5));else if(c&&(c.readUInt32LE||c instanceof Uint8Array))c instanceof Uint8Array&&(c=r.from(c)),c.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=c.length):c.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(c.length,1)),l=o([l,c]);else if(Array.isArray(c))c.length<16?(l=r.allocUnsafe(1))[0]=144|c.length:c.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(c.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(c.length,1)),l=c.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!i&&"function"==typeof c.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var s=4*a,c=i/Math.pow(2,32),u=s+c&4294967295,l=4294967295&i;t.writeInt32BE(u,2),t.writeInt32BE(l,6)}else(t=new r(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(c);if("object"==typeof c)l=function(t){var n,i,a=-1,s=[];for(n=0;n>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(c)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return a(c,t);if(c>=0)if(c<128)(l=r.allocUnsafe(1))[0]=c;else if(c<256)(l=r.allocUnsafe(2))[0]=204,l[1]=c;else if(c<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(c,1);else if(c<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(c,1);else{if(!(c<=9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,c)}else if(c>=-32)(l=r.allocUnsafe(1))[0]=256+c;else if(c>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(c,1);else if(c>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(c,1);else if(c>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(c,1);else{if(!(c>=-9007199254740991))return a(c,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var c=(255^e[s])+a;e[s]=255&c,a=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?l:l.slice()}return s}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId?this.fatalError?(this.logger.log(s.LogLevel.Debug,"Received a new batch "+e+" but errored out on a previous batch "+(this.nextBatchId-1)),[4,n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())]):[3,4]:[3,5];case 3:return o.sent(),[2];case 4:return this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed."),[2];case 5:return o.trys.push([5,7,,8]),this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),[4,this.completeBatch(n,e)];case 6:return o.sent(),[3,8];case 7:throw r=o.sent(),this.fatalError=r.toString(),this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,r.toString()),r;case 8:return[2]}})})},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e}();t.RenderQueue=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(72),o=Math.pow(2,32),i=Math.pow(2,21)-1,a=function(){function e(e){this.batchData=e;var t=new l(e);this.arrayRangeReader=new f(e),this.arrayBuilderSegmentReader=new h(e),this.diffReader=new s(e),this.editReader=new c(e,t),this.frameReader=new u(e,t)}return e.prototype.updatedComponents=function(){return p(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return p(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return p(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return p(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+20*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return p(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+8*t;return g(this.batchData,n)},e}();t.OutOfProcessRenderBatch=a;var s=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return p(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),c=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return p(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return p(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return p(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=p(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),u=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return p(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return p(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return p(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=p(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=p(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return g(this.batchDataUint8,e+12)},e}(),l=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=p(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=p(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<>>0)}function g(e,t){var n=d(e,t+4);if(n>i)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*o+d(e,t)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof TextDecoder?new TextDecoder("utf-8"):null;t.decodeUtf8=r?r.decode.bind(r):function(e){var t=0,n=e.length,r=[],o=[];for(;t65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function s(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}c((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e.prototype.rejected=function(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",function(){return location.reload()})},e}();t.DefaultReconnectDisplay=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.rejected=function(){this.removeClasses(),this.dialog.classList.add(e.RejectedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName,e.RejectedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e.RejectedClassName="components-reconnect-rejected",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";n.r(t);var r=n(6),o=n(11),i=n(2),a=function(){function e(){}return e.write=function(e){var t=e.byteLength||e.length,n=[];do{var r=127&t;(t>>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),c=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary,this.errorResult=1,this.voidResult=2,this.nonVoidResult=3}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,c=a.parse(e);s=3?e[2]:void 0,error:e[1],type:i.MessageType.Close}},e.prototype.createPingMessage=function(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:i.MessageType.Ping}},e.prototype.createInvocationMessage=function(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");var n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:i.MessageType.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:i.MessageType.Invocation}},e.prototype.createStreamItemMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:i.MessageType.StreamItem}},e.prototype.createCompletionMessage=function(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");var n,r,o=t[3];if(o!==this.voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");switch(o){case this.errorResult:n=t[4];break;case this.nonVoidResult:r=t[4]}return{error:n,headers:e,invocationId:t[2],result:r,type:i.MessageType.Completion}},e.prototype.writeInvocation=function(e){var t=o().encode([i.MessageType.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamInvocation=function(e){var t=o().encode([i.MessageType.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]);return a.write(t.slice())},e.prototype.writeStreamItem=function(e){var t=o().encode([i.MessageType.StreamItem,e.headers||{},e.invocationId,e.item]);return a.write(t.slice())},e.prototype.writeCompletion=function(e){var t,n=o(),r=e.error?this.errorResult:e.result?this.nonVoidResult:this.voidResult;switch(r){case this.errorResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.error]);break;case this.voidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r]);break;case this.nonVoidResult:t=n.encode([i.MessageType.Completion,e.headers||{},e.invocationId,r,e.result])}return a.write(t.slice())},e.prototype.writeCancelInvocation=function(e){var t=o().encode([i.MessageType.CancelInvocation,e.headers||{},e.invocationId]);return a.write(t.slice())},e.prototype.readHeaders=function(e){var t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t},e}();n.d(t,"VERSION",function(){return u}),n.d(t,"MessagePackHubProtocol",function(){return c});var u="3.1.0"}]); \ No newline at end of file diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js index 88dbb56b2f41..16dd578625ff 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webassembly.js +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -1 +1 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=47)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(17);var r=n(26),o=n(11),a={},i=!1;function l(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=l,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");l(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),l=r.values(o),u=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function l(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function l(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,l=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var u=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,u)}catch(e){c(i,!1,e)}return l}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]-1?a.substring(0,l):"",s=l>-1?a.substring(l+1):a,c=t.monoPlatform.findMethod(e,u,s,i);t.monoPlatform.callMethod(c,null,r)},callMethod:function(e,n,r){if(r.length>4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),l=Module.stackAlloc(4),u=0;u>2,r=Module.HEAPU32[n+1];if(r>y)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*v+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var w=document.createElement("a");function E(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(32),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(17),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=l,this.editReader=u,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},l={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(18);var r=n(26),o=n(13),a={},i=!1;function u(e,t,n){var o=a[e];o||(o=a[e]=new r.BrowserRenderer(e)),o.attachRootComponentToLogicalElement(n,t)}t.attachRootComponentToLogicalElement=u,t.attachRootComponentToElement=function(e,t,n){var r=document.querySelector(e);if(!r)throw new Error("Could not find any element matching selector '"+e+"'.");u(n||0,o.toLogicalElement(r,!0),t)},t.renderBatch=function(e,t){var n=a[e];if(!n)throw new Error("There is no browser renderer with ID "+e+".");for(var r=t.arrayRangeReader,o=t.updatedComponents(),u=r.values(o),l=r.count(o),s=t.referenceFrames(),c=r.values(s),d=t.diffReader,f=0;f0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function u(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(l(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=l,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=d(t);if(n)return n.previousSibling;var r=l(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):f(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function u(e,t,n,r){var o=s();if(o.invokeDotNetFromJS){var a=JSON.stringify(r,h),i=o.invokeDotNetFromJS(e,t,n,a);return i?d(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function l(e,t,r,a){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var i=o++,u=new Promise(function(e,t){n[i]={resolve:e,reject:t}});try{var l=JSON.stringify(a,h);s().beginInvokeDotNetFromJS(i,e,t,r,l)}catch(e){c(i,!1,e)}return u}function s(){if(null!==a)return a;throw new Error("No .NET call dispatcher has been set.")}function c(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function d(e){return e?JSON.parse(e,function(e,n){return t.reduce(function(t,n){return n(e,t)},n)}):null}function f(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(r.hasOwnProperty(e))return r[e];var t,n=window,o="window";if(e.split(".").forEach(function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e}),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){a=e},e.attachReviver=i,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]>2,r=Module.HEAPU32[n+1];if(r>s)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*l+Module.HEAPU32[n]},readFloatField:function(e,t){return Module.getValue(e+(t||0),"float")},readObjectField:function(e,t){return Module.getValue(e+(t||0),"i32")},readStringField:function(e,n){var r=Module.getValue(e+(n||0),"i32");return 0===r?null:t.monoPlatform.toJavaScriptString(r)},readStructField:function(e,t){return e+(t||0)}};var c=document.createElement("a");function d(e){return e+12}function f(e,t,n){var r="["+e+"] "+t+":"+n;return Module.mono_bind_static_method(r)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(35),o=window.chrome&&navigator.userAgent.indexOf("Edge")<0,a=!1;function i(){return a&&o}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){a=e.some(function(e){return/\.pdb$/.test(r.getFileNameFromUrl(e))});var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(a?o?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Edge(Chromium) or Chrome is supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=a,this.arrayBuilderSegmentReader=i,this.diffReader=u,this.editReader=l,this.frameReader=s}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,a.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*a.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*a.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,u.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var a={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},i={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},u={structLength:4+i.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,l.structLength)}},l={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},s={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}}]); \ No newline at end of file From 4360535bab6f958a91b06dfcd31c539bbffa9a5a Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 3 Feb 2020 21:49:44 +0000 Subject: [PATCH 065/322] Update to newer ws-proxy sources (#18760) * Update to latest ws-proxy sources * Changes needed inside ws-proxy sources for inclusion in Microsoft.AspNetCore.Blazor.Server * Use ILogger in ws-proxy * Fix for /json endpoint when on HTTPS --- ...lazorMonoDebugProxyAppBuilderExtensions.cs | 15 +- .../src/MonoDebugProxy/ws-proxy/DebugStore.cs | 117 +++++---- .../MonoDebugProxy/ws-proxy/DevToolsClient.cs | 139 +++++++++++ .../ws-proxy/{WsProxy.cs => DevToolsProxy.cs} | 166 ++++++++----- .../src/MonoDebugProxy/ws-proxy/MonoProxy.cs | 222 ++++++++++-------- 5 files changed, 444 insertions(+), 215 deletions(-) create mode 100644 src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsClient.cs rename src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/{WsProxy.cs => DevToolsProxy.cs} (57%) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs index cbe0fe363a67..078384de48ff 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/BlazorMonoDebugProxyAppBuilderExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Net; @@ -12,7 +11,9 @@ using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using WsProxy; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using WebAssembly.Net.Debugging; namespace Microsoft.AspNetCore.Builder { @@ -50,7 +51,8 @@ public static void UseBlazorDebugging(this IApplicationBuilder app) if (requestPath.Equals("/_framework/debug/ws-proxy", StringComparison.OrdinalIgnoreCase)) { - return DebugWebSocketProxyRequest(context); + var loggerFactory = app.ApplicationServices.GetRequiredService(); + return DebugWebSocketProxyRequest(loggerFactory, context); } if (requestPath.Equals("/_framework/debug", StringComparison.OrdinalIgnoreCase)) @@ -111,7 +113,8 @@ private static void UseVisualStudioDebuggerConnectionRequestHandlers(this IAppli var proxiedTabInfos = availableTabs.Select(tab => { var underlyingV8Endpoint = tab.WebSocketDebuggerUrl; - var proxiedV8Endpoint = $"ws://{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}"; + var proxiedScheme = request.IsHttps ? "wss" : "ws"; + var proxiedV8Endpoint = $"{proxiedScheme}://{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}"; return new { description = "", @@ -142,7 +145,7 @@ private static void UseVisualStudioDebuggerConnectionRequestHandlers(this IAppli }); } - private static async Task DebugWebSocketProxyRequest(HttpContext context) + private static async Task DebugWebSocketProxyRequest(ILoggerFactory loggerFactory, HttpContext context) { if (!context.WebSockets.IsWebSocketRequest) { @@ -152,7 +155,7 @@ private static async Task DebugWebSocketProxyRequest(HttpContext context) var browserUri = new Uri(context.Request.Query["browser"]); var ideSocket = await context.WebSockets.AcceptWebSocketAsync(); - await new MonoProxy().Run(browserUri, ideSocket); + await new MonoProxy(loggerFactory).Run(browserUri, ideSocket); } private static async Task DebugHome(HttpContext context) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs index e1e9b7392ba8..5c46bc7324a3 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DebugStore.cs @@ -9,8 +9,10 @@ using Mono.Cecil.Pdb; using Newtonsoft.Json; using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Threading; -namespace WsProxy { +namespace WebAssembly.Net.Debugging { internal class BreakPointRequest { public string Assembly { get; private set; } public string File { get; private set; } @@ -23,13 +25,15 @@ public override string ToString () { public static BreakPointRequest Parse (JObject args, DebugStore store) { - if (args == null) + // Events can potentially come out of order, so DebugStore may not be initialized + // The BP being set in these cases are JS ones, which we can safely ignore + if (args == null || store == null) return null; var url = args? ["url"]?.Value (); if (url == null) { var urlRegex = args?["urlRegex"].Value(); - var sourceFile = store.GetFileByUrlRegex (urlRegex); + var sourceFile = store?.GetFileByUrlRegex (urlRegex); url = sourceFile?.DotNetUrl; } @@ -72,7 +76,6 @@ public static BreakPointRequest Parse (JObject args, DebugStore store) } } - internal class VarInfo { public VarInfo (VariableDebugInformation v) { @@ -85,10 +88,10 @@ public VarInfo (ParameterDefinition p) this.Name = p.Name; this.Index = (p.Index + 1) * -1; } + public string Name { get; private set; } public int Index { get; private set; } - public override string ToString () { return $"(var-info [{Index}] '{Name}')"; @@ -97,18 +100,14 @@ public override string ToString () internal class CliLocation { - - private MethodInfo method; - private int offset; - public CliLocation (MethodInfo method, int offset) { - this.method = method; - this.offset = offset; + Method = method; + Offset = offset; } - public MethodInfo Method { get => method; } - public int Offset { get => offset; } + public MethodInfo Method { get; private set; } + public int Offset { get; private set; } } @@ -282,7 +281,6 @@ public VarInfo [] GetLiveVarsAt (int offset) .Where (v => !v.IsDebuggerHidden) .Select (v => new VarInfo (v))); - return res.ToArray (); } } @@ -294,20 +292,21 @@ internal class AssemblyInfo { Dictionary methods = new Dictionary (); Dictionary sourceLinkMappings = new Dictionary(); readonly List sources = new List(); + internal string Url { get; private set; } - public AssemblyInfo (byte[] assembly, byte[] pdb) + public AssemblyInfo (string url, byte[] assembly, byte[] pdb) { lock (typeof (AssemblyInfo)) { this.id = ++next_id; } try { + Url = url; ReaderParameters rp = new ReaderParameters (/*ReadingMode.Immediate*/); - if (pdb != null) { - rp.ReadSymbols = true; - rp.SymbolReaderProvider = new PortablePdbReaderProvider (); + rp.ReadSymbols = true; + rp.SymbolReaderProvider = new PdbReaderProvider (); + if (pdb != null) rp.SymbolStream = new MemoryStream (pdb); - } rp.ReadingMode = ReadingMode.Immediate; rp.InMemory = true; @@ -315,13 +314,16 @@ public AssemblyInfo (byte[] assembly, byte[] pdb) this.image = ModuleDefinition.ReadModule (new MemoryStream (assembly), rp); } catch (BadImageFormatException ex) { Console.WriteLine ($"Failed to read assembly as portable PDB: {ex.Message}"); + } catch (ArgumentNullException) { + if (pdb != null) + throw; } if (this.image == null) { ReaderParameters rp = new ReaderParameters (/*ReadingMode.Immediate*/); if (pdb != null) { rp.ReadSymbols = true; - rp.SymbolReaderProvider = new NativePdbReaderProvider (); + rp.SymbolReaderProvider = new PdbReaderProvider (); rp.SymbolStream = new MemoryStream (pdb); } @@ -491,61 +493,72 @@ internal void AddMethod (MethodInfo mi) } internal class DebugStore { + // MonoProxy proxy; - commenting out because never gets assigned List assemblies = new List (); + HttpClient client = new HttpClient (); + + class DebugItem { + public string Url { get; set; } + public Task Data { get; set; } + } - public DebugStore (string [] loaded_files) + public async Task Load (SessionId sessionId, string [] loaded_files, CancellationToken token) { - bool MatchPdb (string asm, string pdb) - { - return Path.ChangeExtension (asm, "pdb") == pdb; - } + static bool MatchPdb (string asm, string pdb) + => Path.ChangeExtension (asm, "pdb") == pdb; var asm_files = new List (); var pdb_files = new List (); - foreach (var f in loaded_files) { - var file_name = f; + foreach (var file_name in loaded_files) { if (file_name.EndsWith (".pdb", StringComparison.OrdinalIgnoreCase)) pdb_files.Add (file_name); else asm_files.Add (file_name); } - //FIXME make this parallel - foreach (var p in asm_files) { + List steps = new List (); + foreach (var url in asm_files) { try { - var pdb = pdb_files.FirstOrDefault (n => MatchPdb (p, n)); - HttpClient h = new HttpClient (); - var assembly_bytes = h.GetByteArrayAsync (p).Result; - byte [] pdb_bytes = null; - if (pdb != null) - pdb_bytes = h.GetByteArrayAsync (pdb).Result; - - this.assemblies.Add (new AssemblyInfo (assembly_bytes, pdb_bytes)); + var pdb = pdb_files.FirstOrDefault (n => MatchPdb (url, n)); + steps.Add ( + new DebugItem { + Url = url, + Data = Task.WhenAll (client.GetByteArrayAsync (url), pdb != null ? client.GetByteArrayAsync (pdb) : Task.FromResult (null)) + }); } catch (Exception e) { - Console.WriteLine ($"Failed to read {p} ({e.Message})"); + Console.WriteLine ($"Failed to read {url} ({e.Message})"); + var o = JObject.FromObject (new { + entry = new { + source = "other", + level = "warning", + text = $"Failed to read {url} ({e.Message})" + } + }); + // proxy.SendEvent (sessionId, "Log.entryAdded", o, token); - commenting out because `proxy` would always be null + } } - } - public IEnumerable AllSources () - { - foreach (var a in assemblies) { - foreach (var s in a.Sources) - yield return s; + foreach (var step in steps) { + try { + var bytes = await step.Data; + assemblies.Add (new AssemblyInfo (step.Url, bytes[0], bytes[1])); + } catch (Exception e) { + Console.WriteLine ($"Failed to Load {step.Url} ({e.Message})"); + } } } + public IEnumerable AllSources () + => assemblies.SelectMany (a => a.Sources); + public SourceFile GetFileById (SourceId id) - { - return AllSources ().FirstOrDefault (f => f.SourceId.Equals (id)); - } + => AllSources ().FirstOrDefault (f => f.SourceId.Equals (id)); public AssemblyInfo GetAssemblyByName (string name) - { - return assemblies.FirstOrDefault (a => a.Name.Equals (name, StringComparison.InvariantCultureIgnoreCase)); - } + => assemblies.FirstOrDefault (a => a.Name.Equals (name, StringComparison.InvariantCultureIgnoreCase)); - /* + /* V8 uses zero based indexing for both line and column. PPDBs uses one based indexing for both line and column. */ @@ -598,7 +611,7 @@ public List FindPossibleBreakpoints (SourceLocation start, Sourc PPDBs uses one based indexing for both line and column. */ static bool Match (SequencePoint sp, int line, int column) - { + { var bp = (line: line + 1, column: column + 1); if (sp.StartLine > bp.line || sp.EndLine < bp.line) diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsClient.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsClient.cs new file mode 100644 index 000000000000..3fa95ef3463a --- /dev/null +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsClient.cs @@ -0,0 +1,139 @@ +using System; +using System.Threading.Tasks; + +using System.Net.WebSockets; +using System.Threading; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace WebAssembly.Net.Debugging { + internal class DevToolsClient: IDisposable { + ClientWebSocket socket; + List pending_ops = new List (); + TaskCompletionSource side_exit = new TaskCompletionSource (); + List pending_writes = new List (); + Task current_write; + + public DevToolsClient () { + } + + ~DevToolsClient() { + Dispose(false); + } + + public void Dispose() { + Dispose(true); + } + + public async Task Close (CancellationToken cancellationToken) + { + if (socket.State == WebSocketState.Open) + await socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, "Closing", cancellationToken); + } + + protected virtual void Dispose (bool disposing) { + if (disposing) + socket.Dispose (); + } + + Task Pump (Task task, CancellationToken token) + { + if (task != current_write) + return null; + current_write = null; + + pending_writes.RemoveAt (0); + + if (pending_writes.Count > 0) { + current_write = socket.SendAsync (new ArraySegment (pending_writes [0]), WebSocketMessageType.Text, true, token); + return current_write; + } + return null; + } + + async Task ReadOne (CancellationToken token) + { + byte [] buff = new byte [4000]; + var mem = new MemoryStream (); + while (true) { + var result = await this.socket.ReceiveAsync (new ArraySegment (buff), token); + if (result.MessageType == WebSocketMessageType.Close) { + return null; + } + + if (result.EndOfMessage) { + mem.Write (buff, 0, result.Count); + return Encoding.UTF8.GetString (mem.GetBuffer (), 0, (int)mem.Length); + } else { + mem.Write (buff, 0, result.Count); + } + } + } + + protected void Send (byte [] bytes, CancellationToken token) + { + pending_writes.Add (bytes); + if (pending_writes.Count == 1) { + if (current_write != null) + throw new Exception ("Internal state is bad. current_write must be null if there are no pending writes"); + + current_write = socket.SendAsync (new ArraySegment (bytes), WebSocketMessageType.Text, true, token); + pending_ops.Add (current_write); + } + } + + async Task MarkCompleteAfterward (Func send, CancellationToken token) + { + try { + await send(token); + side_exit.SetResult (true); + } catch (Exception e) { + side_exit.SetException (e); + } + } + + protected async Task ConnectWithMainLoops( + Uri uri, + Func receive, + Func send, + CancellationToken token) { + + Console.WriteLine ("connecting to {0}", uri); + this.socket = new ClientWebSocket (); + this.socket.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan; + + await this.socket.ConnectAsync (uri, token); + pending_ops.Add (ReadOne (token)); + pending_ops.Add (side_exit.Task); + pending_ops.Add (MarkCompleteAfterward (send, token)); + + while (!token.IsCancellationRequested) { + var task = await Task.WhenAny (pending_ops); + if (task == pending_ops [0]) { //pending_ops[0] is for message reading + var msg = ((Task)task).Result; + pending_ops [0] = ReadOne (token); + Task tsk = receive (msg, token); + if (tsk != null) + pending_ops.Add (tsk); + } else if (task == pending_ops [1]) { + var res = ((Task)task).Result; + //it might not throw if exiting successfull + return res; + } else { //must be a background task + pending_ops.Remove (task); + var tsk = Pump (task, token); + if (tsk != null) + pending_ops.Add (tsk); + } + } + + return false; + } + + protected virtual void Log (string priority, string msg) + { + // + } + } +} diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsProxy.cs similarity index 57% rename from src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs rename to src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsProxy.cs index 87ef23027e8a..e2e24eff7942 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/WsProxy.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/DevToolsProxy.cs @@ -8,8 +8,16 @@ using System.IO; using System.Text; using System.Collections.Generic; +using Microsoft.Extensions.Logging; -namespace WsProxy { +namespace WebAssembly.Net.Debugging { + internal class SessionId { + public string sessionId; + } + + internal class MessageId : SessionId { + public int id; + } internal struct Result { public JObject Value { get; private set; } @@ -26,6 +34,7 @@ internal struct Result { public static Result FromJson (JObject obj) { + //Log ("protocol", $"from result: {obj}"); return new Result (obj ["result"] as JObject, obj ["error"] as JObject); } @@ -39,28 +48,30 @@ public static Result Err (JObject err) return new Result (null, err); } - public JObject ToJObject (int id) { + public JObject ToJObject (MessageId target) { if (IsOk) { return JObject.FromObject (new { - id = id, + target.id, + target.sessionId, result = Value }); } else { return JObject.FromObject (new { - id = id, + target.id, + target.sessionId, error = Error }); } } } - class WsQueue { + class DevToolsQueue { Task current_send; List pending; public WebSocket Ws { get; private set; } public Task CurrentSend { get { return current_send; } } - public WsQueue (WebSocket sock) + public DevToolsQueue (WebSocket sock) { this.Ws = sock; pending = new List (); @@ -71,7 +82,7 @@ public Task Send (byte [] bytes, CancellationToken token) pending.Add (bytes); if (pending.Count == 1) { if (current_send != null) - throw new Exception ("UNEXPECTED, current_send MUST BE NULL IF THERE'S no pending send"); + throw new Exception ("current_send MUST BE NULL IF THERE'S no pending send"); //Console.WriteLine ("sending {0} bytes", bytes.Length); current_send = Ws.SendAsync (new ArraySegment (bytes), WebSocketMessageType.Text, true, token); return current_send; @@ -86,7 +97,7 @@ public Task Pump (CancellationToken token) if (pending.Count > 0) { if (current_send != null) - throw new Exception ("UNEXPECTED, current_send MUST BE NULL IF THERE'S no pending send"); + throw new Exception ("current_send MUST BE NULL IF THERE'S no pending send"); //Console.WriteLine ("sending more {0} bytes", pending[0].Length); current_send = Ws.SendAsync (new ArraySegment (pending [0]), WebSocketMessageType.Text, true, token); return current_send; @@ -95,22 +106,28 @@ public Task Pump (CancellationToken token) } } - internal class WsProxy { + internal class DevToolsProxy { TaskCompletionSource side_exception = new TaskCompletionSource (); TaskCompletionSource client_initiated_close = new TaskCompletionSource (); - List<(int, TaskCompletionSource)> pending_cmds = new List<(int, TaskCompletionSource)> (); + List<(MessageId, TaskCompletionSource)> pending_cmds = new List<(MessageId, TaskCompletionSource)> (); ClientWebSocket browser; WebSocket ide; int next_cmd_id; List pending_ops = new List (); - List queues = new List (); + List queues = new List (); + readonly ILogger logger; + + public DevToolsProxy(ILoggerFactory loggerFactory) + { + logger = loggerFactory.CreateLogger(); + } - protected virtual Task AcceptEvent (string method, JObject args, CancellationToken token) + protected virtual Task AcceptEvent (SessionId sessionId, string method, JObject args, CancellationToken token) { return Task.FromResult (false); } - protected virtual Task AcceptCommand (int id, string method, JObject args, CancellationToken token) + protected virtual Task AcceptCommand (MessageId id, string method, JObject args, CancellationToken token) { return Task.FromResult (false); } @@ -122,7 +139,7 @@ async Task ReadOne (WebSocket socket, CancellationToken token) while (true) { if (socket.State != WebSocketState.Open) { - Console.WriteLine ($"WSProxy: Socket is no longer open."); + Log ("error", $"DevToolsProxy: Socket is no longer open."); client_initiated_close.TrySetResult (true); return null; } @@ -133,51 +150,53 @@ async Task ReadOne (WebSocket socket, CancellationToken token) return null; } - if (result.EndOfMessage) { - mem.Write (buff, 0, result.Count); + mem.Write (buff, 0, result.Count); + + if (result.EndOfMessage) return Encoding.UTF8.GetString (mem.GetBuffer (), 0, (int)mem.Length); - } else { - mem.Write (buff, 0, result.Count); - } } } - WsQueue GetQueueForSocket (WebSocket ws) + DevToolsQueue GetQueueForSocket (WebSocket ws) { return queues.FirstOrDefault (q => q.Ws == ws); } - WsQueue GetQueueForTask (Task task) { + DevToolsQueue GetQueueForTask (Task task) + { return queues.FirstOrDefault (q => q.CurrentSend == task); } void Send (WebSocket to, JObject o, CancellationToken token) { - var bytes = Encoding.UTF8.GetBytes (o.ToString ()); + var sender = browser == to ? "Send-browser" : "Send-ide"; + Log ("protocol", $"{sender}: {o}"); + var bytes = Encoding.UTF8.GetBytes (o.ToString ()); var queue = GetQueueForSocket (to); + var task = queue.Send (bytes, token); if (task != null) pending_ops.Add (task); } - async Task OnEvent (string method, JObject args, CancellationToken token) + async Task OnEvent (SessionId sessionId, string method, JObject args, CancellationToken token) { try { - if (!await AcceptEvent (method, args, token)) { + if (!await AcceptEvent (sessionId, method, args, token)) { //Console.WriteLine ("proxy browser: {0}::{1}",method, args); - SendEventInternal (method, args, token); + SendEventInternal (sessionId, method, args, token); } } catch (Exception e) { side_exception.TrySetException (e); } } - async Task OnCommand (int id, string method, JObject args, CancellationToken token) + async Task OnCommand (MessageId id, string method, JObject args, CancellationToken token) { try { if (!await AcceptCommand (id, method, args, token)) { - var res = await SendCommandInternal (method, args, token); + var res = await SendCommandInternal (id, method, args, token); SendResponseInternal (id, res, token); } } catch (Exception e) { @@ -185,10 +204,11 @@ async Task OnCommand (int id, string method, JObject args, CancellationToken tok } } - void OnResponse (int id, Result result) + void OnResponse (MessageId id, Result result) { //Console.WriteLine ("got id {0} res {1}", id, result); - var idx = pending_cmds.FindIndex (e => e.Item1 == id); + // Fixme + var idx = pending_cmds.FindIndex (e => e.Item1.id == id.id && e.Item1.sessionId == id.sessionId); var item = pending_cmds [idx]; pending_cmds.RemoveAt (idx); @@ -197,68 +217,74 @@ void OnResponse (int id, Result result) void ProcessBrowserMessage (string msg, CancellationToken token) { - // Debug ($"browser: {msg}"); + Log ("protocol", $"browser: {msg}"); var res = JObject.Parse (msg); if (res ["id"] == null) - pending_ops.Add (OnEvent (res ["method"].Value (), res ["params"] as JObject, token)); + pending_ops.Add (OnEvent (new SessionId { sessionId = res ["sessionId"]?.Value () }, res ["method"].Value (), res ["params"] as JObject, token)); else - OnResponse (res ["id"].Value (), Result.FromJson (res)); + OnResponse (new MessageId { id = res ["id"].Value (), sessionId = res ["sessionId"]?.Value () }, Result.FromJson (res)); } void ProcessIdeMessage (string msg, CancellationToken token) { + Log ("protocol", $"ide: {msg}"); if (!string.IsNullOrEmpty (msg)) { var res = JObject.Parse (msg); - pending_ops.Add (OnCommand (res ["id"].Value (), res ["method"].Value (), res ["params"] as JObject, token)); + pending_ops.Add (OnCommand (new MessageId { id = res ["id"].Value (), sessionId = res ["sessionId"]?.Value () }, res ["method"].Value (), res ["params"] as JObject, token)); } } - internal async Task SendCommand (string method, JObject args, CancellationToken token) { - // Debug ($"sending command {method}: {args}"); - return await SendCommandInternal (method, args, token); + internal async Task SendCommand (SessionId id, string method, JObject args, CancellationToken token) { + //Log ("verbose", $"sending command {method}: {args}"); + return await SendCommandInternal (id, method, args, token); } - Task SendCommandInternal (string method, JObject args, CancellationToken token) + Task SendCommandInternal (SessionId sessionId, string method, JObject args, CancellationToken token) { int id = ++next_cmd_id; var o = JObject.FromObject (new { - id = id, - method = method, + sessionId.sessionId, + id, + method, @params = args }); var tcs = new TaskCompletionSource (); - //Console.WriteLine ("add cmd id {0}", id); - pending_cmds.Add ((id, tcs)); + + + var msgId = new MessageId { id = id, sessionId = sessionId.sessionId }; + //Log ("verbose", $"add cmd id {sessionId}-{id}"); + pending_cmds.Add ((msgId , tcs)); Send (this.browser, o, token); return tcs.Task; } - public void SendEvent (string method, JObject args, CancellationToken token) + public void SendEvent (SessionId sessionId, string method, JObject args, CancellationToken token) { - //Debug ($"sending event {method}: {args}"); - SendEventInternal (method, args, token); + //Log ("verbose", $"sending event {method}: {args}"); + SendEventInternal (sessionId, method, args, token); } - void SendEventInternal (string method, JObject args, CancellationToken token) + void SendEventInternal (SessionId sessionId, string method, JObject args, CancellationToken token) { var o = JObject.FromObject (new { - method = method, + sessionId.sessionId, + method, @params = args }); Send (this.ide, o, token); } - internal void SendResponse (int id, Result result, CancellationToken token) + internal void SendResponse (MessageId id, Result result, CancellationToken token) { - //Debug ($"sending response: {id}: {result.ToJObject (id)}"); + //Log ("verbose", $"sending response: {id}: {result.ToJObject (id)}"); SendResponseInternal (id, result, token); } - void SendResponseInternal (int id, Result result, CancellationToken token) + void SendResponseInternal (MessageId id, Result result, CancellationToken token) { JObject o = result.ToJObject (id); @@ -268,16 +294,16 @@ void SendResponseInternal (int id, Result result, CancellationToken token) // , HttpContext context) public async Task Run (Uri browserUri, WebSocket ideSocket) { - Debug ($"WsProxy Starting on {browserUri}"); + Log ("info", $"DevToolsProxy: Starting on {browserUri}"); using (this.ide = ideSocket) { - Debug ($"WsProxy: IDE waiting for connection on {browserUri}"); - queues.Add (new WsQueue (this.ide)); + Log ("verbose", $"DevToolsProxy: IDE waiting for connection on {browserUri}"); + queues.Add (new DevToolsQueue (this.ide)); using (this.browser = new ClientWebSocket ()) { this.browser.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan; await this.browser.ConnectAsync (browserUri, CancellationToken.None); - queues.Add (new WsQueue (this.browser)); + queues.Add (new DevToolsQueue (this.browser)); - Debug ($"WsProxy: Client connected on {browserUri}"); + Log ("verbose", $"DevToolsProxy: Client connected on {browserUri}"); var x = new CancellationTokenSource (); pending_ops.Add (ReadOne (browser, x.Token)); @@ -306,7 +332,7 @@ public async Task Run (Uri browserUri, WebSocket ideSocket) throw new Exception ("side task must always complete with an exception, what's going on???"); } else if (task == pending_ops [3]) { var res = ((Task)task).Result; - Debug ($"WsProxy: Client initiated close from {browserUri}"); + Log ("verbose", $"DevToolsProxy: Client initiated close from {browserUri}"); x.Cancel (); } else { //must be a background task @@ -320,7 +346,7 @@ public async Task Run (Uri browserUri, WebSocket ideSocket) } } } catch (Exception e) { - Debug ($"WsProxy::Run: Exception {e}"); + Log ("error", $"DevToolsProxy::Run: Exception {e}"); //throw; } finally { if (!x.IsCancellationRequested) @@ -330,14 +356,28 @@ public async Task Run (Uri browserUri, WebSocket ideSocket) } } - protected void Debug (string msg) + protected void Log (string priority, string msg) { - Console.WriteLine (msg); - } - - protected void Info (string msg) - { - Console.WriteLine (msg); + switch (priority) { + case "protocol": + logger.LogTrace (msg); + break; + case "verbose": + logger.LogDebug (msg); + break; + case "info": + logger.LogInformation(msg); + break; + case "warning": + logger.LogWarning(msg); + break; + case "error": + logger.LogError (msg); + break; + default: + logger.LogError(msg); + break; + } } } } diff --git a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs index eb4cf65b50a4..e74d46849486 100644 --- a/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs +++ b/src/Components/Blazor/Server/src/MonoDebugProxy/ws-proxy/MonoProxy.cs @@ -3,14 +3,13 @@ using System.Threading.Tasks; using Newtonsoft.Json.Linq; -using System.Net.WebSockets; using System.Threading; using System.IO; -using System.Text; using System.Collections.Generic; using System.Net; +using Microsoft.Extensions.Logging; -namespace WsProxy { +namespace WebAssembly.Net.Debugging { internal class MonoCommands { public const string GET_CALL_STACK = "MONO.mono_wasm_get_call_stack()"; @@ -29,10 +28,10 @@ internal enum MonoErrorCodes { BpNotFound = 100000, } - internal class MonoConstants { public const string RUNTIME_IS_READY = "mono_wasm_runtime_ready"; } + class Frame { public Frame (MethodInfo method, SourceLocation location, int id) { @@ -73,7 +72,7 @@ enum StepKind { Over } - internal class MonoProxy : WsProxy { + internal class MonoProxy : DevToolsProxy { DebugStore store; List breakpoints = new List (); List current_callstack; @@ -82,9 +81,9 @@ internal class MonoProxy : WsProxy { int ctx_id; JObject aux_ctx_data; - public MonoProxy () { } + public MonoProxy (ILoggerFactory loggerFactory) : base(loggerFactory) { } - protected override async Task AcceptEvent (string method, JObject args, CancellationToken token) + protected override async Task AcceptEvent (SessionId sessionId, string method, JObject args, CancellationToken token) { switch (method) { case "Runtime.executionContextCreated": { @@ -93,8 +92,8 @@ protected override async Task AcceptEvent (string method, JObject args, Ca if (aux_data != null) { var is_default = aux_data ["isDefault"]?.Value (); if (is_default == true) { - var ctx_id = ctx ["id"].Value (); - await OnDefaultContext (ctx_id, aux_data, token); + var id = new MessageId { id = ctx ["id"].Value (), sessionId = sessionId.sessionId }; + await OnDefaultContext (id, aux_data, token); } } break; @@ -103,11 +102,11 @@ protected override async Task AcceptEvent (string method, JObject args, Ca //TODO figure out how to stich out more frames and, in particular what happens when real wasm is on the stack var top_func = args? ["callFrames"]? [0]? ["functionName"]?.Value (); if (top_func == "mono_wasm_fire_bp" || top_func == "_mono_wasm_fire_bp") { - await OnBreakPointHit (args, token); + await OnBreakPointHit (sessionId, args, token); return true; } if (top_func == MonoConstants.RUNTIME_IS_READY) { - await OnRuntimeReady (token); + await OnRuntimeReady (new SessionId { sessionId = sessionId.sessionId }, token); return true; } break; @@ -119,24 +118,33 @@ protected override async Task AcceptEvent (string method, JObject args, Ca } break; } + case "Debugger.enabled": { + await LoadStore (new SessionId { sessionId = args? ["sessionId"]?.Value () }, token); + break; + } } - return false; } - protected override async Task AcceptCommand (int id, string method, JObject args, CancellationToken token) + protected override async Task AcceptCommand (MessageId id, string method, JObject args, CancellationToken token) { switch (method) { + case "Target.attachToTarget": { + break; + } + case "Target.attachToBrowserTarget": { + break; + } case "Debugger.getScriptSource": { var script_id = args? ["scriptId"]?.Value (); if (script_id.StartsWith ("dotnet://", StringComparison.InvariantCultureIgnoreCase)) { await OnGetScriptSource (id, script_id, token); return true; } - break; } + case "Runtime.compileScript": { var exp = args? ["expression"]?.Value (); if (exp.StartsWith ("//dotnet:", StringComparison.InvariantCultureIgnoreCase)) { @@ -156,7 +164,7 @@ protected override async Task AcceptCommand (int id, string method, JObjec } case "Debugger.setBreakpointByUrl": { - Info ($"BP req {args}"); + Log ("info", $"BP req {args}"); var bp_req = BreakPointRequest.Parse (args, store); if (bp_req != null) { await SetBreakPoint (id, bp_req, token); @@ -164,9 +172,10 @@ protected override async Task AcceptCommand (int id, string method, JObjec } break; } + case "Debugger.removeBreakpoint": { - return await RemoveBreakpoint (id, args, token); - } + return await RemoveBreakpoint (id, args, token); + } case "Debugger.resume": { await OnResume (token); @@ -199,16 +208,24 @@ protected override async Task AcceptCommand (int id, string method, JObjec case "Runtime.getProperties": { var objId = args? ["objectId"]?.Value (); - if (objId.StartsWith ("dotnet:scope:", StringComparison.InvariantCulture)) { - await GetScopeProperties (id, int.Parse (objId.Substring ("dotnet:scope:".Length)), token); - return true; - } - if (objId.StartsWith("dotnet:", StringComparison.InvariantCulture)) - { - if (objId.StartsWith("dotnet:object:", StringComparison.InvariantCulture)) - await GetDetails(id, int.Parse(objId.Substring("dotnet:object:".Length)), token, MonoCommands.GET_OBJECT_PROPERTIES); - if (objId.StartsWith("dotnet:array:", StringComparison.InvariantCulture)) - await GetDetails(id, int.Parse(objId.Substring("dotnet:array:".Length)), token, MonoCommands.GET_ARRAY_VALUES); + if (objId.StartsWith ("dotnet:")) { + var parts = objId.Split (new char [] { ':' }); + if (parts.Length < 3) + return true; + switch (parts[1]) { + case "scope": { + await GetScopeProperties (id, int.Parse (parts[2]), token); + break; + } + case "object": { + await GetDetails (id, int.Parse (parts[2]), token, MonoCommands.GET_OBJECT_PROPERTIES); + break; + } + case "array": { + await GetDetails (id, int.Parse (parts[2]), token, MonoCommands.GET_ARRAY_VALUES); + break; + } + } return true; } break; @@ -218,15 +235,16 @@ protected override async Task AcceptCommand (int id, string method, JObjec return false; } - async Task OnRuntimeReady (CancellationToken token) + async Task OnRuntimeReady (SessionId sessionId, CancellationToken token) { - Info ("RUNTIME READY, PARTY TIME"); - await RuntimeReady (token); - await SendCommand ("Debugger.resume", new JObject (), token); - SendEvent ("Mono.runtimeReady", new JObject (), token); + Log ("info", "RUNTIME READY, PARTY TIME"); + await RuntimeReady (sessionId, token); + await SendCommand (sessionId, "Debugger.resume", new JObject (), token); + SendEvent (sessionId, "Mono.runtimeReady", new JObject (), token); } - async Task OnBreakPointHit (JObject args, CancellationToken token) + //static int frame_id=0; + async Task OnBreakPointHit (SessionId sessionId, JObject args, CancellationToken token) { //FIXME we should send release objects every now and then? Or intercept those we inject and deal in the runtime var o = JObject.FromObject (new { @@ -238,11 +256,11 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) }); var orig_callframes = args? ["callFrames"]?.Values (); - var res = await SendCommand ("Runtime.evaluate", o, token); + var res = await SendCommand (sessionId, "Runtime.evaluate", o, token); if (res.IsErr) { //Give up and send the original call stack - SendEvent ("Debugger.paused", args, token); + SendEvent (sessionId, "Debugger.paused", args, token); return; } @@ -250,16 +268,16 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) var res_value = res.Value? ["result"]? ["value"]; if (res_value == null || res_value is JValue) { //Give up and send the original call stack - SendEvent ("Debugger.paused", args, token); + SendEvent (sessionId, "Debugger.paused", args, token); return; } - Debug ($"call stack (err is {res.Error} value is:\n{res.Value}"); + Log ("verbose", $"call stack (err is {res.Error} value is:\n{res.Value}"); var bp_id = res_value? ["breakpoint_id"]?.Value (); - Debug ($"We just hit bp {bp_id}"); + Log ("verbose", $"We just hit bp {bp_id}"); if (!bp_id.HasValue) { //Give up and send the original call stack - SendEvent ("Debugger.paused", args, token); + SendEvent (sessionId, "Debugger.paused", args, token); return; } var bp = this.breakpoints.FirstOrDefault (b => b.RemoteId == bp_id.Value); @@ -282,14 +300,14 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) var asm = store.GetAssemblyByName (assembly_name); if (asm == null) { - Info ($"Unable to find assembly: {assembly_name}"); + Log ("info",$"Unable to find assembly: {assembly_name}"); continue; } var method = asm.GetMethodByToken (method_token); if (method == null) { - Info ($"Unable to find il offset: {il_pos} in method token: {method_token} assembly name: {assembly_name}"); + Log ("info", $"Unable to find il offset: {il_pos} in method token: {method_token} assembly name: {assembly_name}"); continue; } @@ -303,8 +321,8 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) continue; } - Info ($"frame il offset: {il_pos} method token: {method_token} assembly name: {assembly_name}"); - Info ($"\tmethod {method.Name} location: {location}"); + Log ("info", $"frame il offset: {il_pos} method token: {method_token} assembly name: {assembly_name}"); + Log ("info", $"\tmethod {method.Name} location: {location}"); frames.Add (new Frame (method, location, frame_id)); callFrames.Add (JObject.FromObject (new { @@ -351,12 +369,12 @@ async Task OnBreakPointHit (JObject args, CancellationToken token) hitBreakpoints = bp_list, }); - SendEvent ("Debugger.paused", o, token); + SendEvent (sessionId, "Debugger.paused", o, token); } - async Task OnDefaultContext (int ctx_id, JObject aux_data, CancellationToken token) + async Task OnDefaultContext (MessageId ctx_id, JObject aux_data, CancellationToken token) { - Debug ("Default context created, clearing state and sending events"); + Log ("verbose", "Default context created, clearing state and sending events"); //reset all bps foreach (var b in this.breakpoints){ @@ -371,16 +389,16 @@ async Task OnDefaultContext (int ctx_id, JObject aux_data, CancellationToken tok silent = false, returnByValue = true }); - this.ctx_id = ctx_id; + this.ctx_id = ctx_id.id; this.aux_ctx_data = aux_data; - Debug ("checking if the runtime is ready"); - var res = await SendCommand ("Runtime.evaluate", o, token); + Log ("verbose", "checking if the runtime is ready"); + var res = await SendCommand (ctx_id, "Runtime.evaluate", o, token); var is_ready = res.Value? ["result"]? ["value"]?.Value (); - //Debug ($"\t{is_ready}"); + //Log ("verbose", $"\t{is_ready}"); if (is_ready.HasValue && is_ready.Value == true) { - Debug ("RUNTIME LOOK READY. GO TIME!"); - await OnRuntimeReady (token); + Log ("verbose", "RUNTIME LOOK READY. GO TIME!"); + await OnRuntimeReady (ctx_id, token); } } @@ -392,7 +410,7 @@ async Task OnResume (CancellationToken token) await Task.CompletedTask; } - async Task Step (int msg_id, StepKind kind, CancellationToken token) + async Task Step (MessageId msg_id, StepKind kind, CancellationToken token) { var o = JObject.FromObject (new { @@ -403,16 +421,16 @@ async Task Step (int msg_id, StepKind kind, CancellationToken token) returnByValue = true, }); - var res = await SendCommand ("Runtime.evaluate", o, token); + var res = await SendCommand (msg_id, "Runtime.evaluate", o, token); SendResponse (msg_id, Result.Ok (new JObject ()), token); this.current_callstack = null; - await SendCommand ("Debugger.resume", new JObject (), token); + await SendCommand (msg_id, "Debugger.resume", new JObject (), token); } - async Task GetDetails(int msg_id, int object_id, CancellationToken token, string command) + async Task GetDetails(MessageId msg_id, int object_id, CancellationToken token, string command) { var o = JObject.FromObject(new { @@ -423,7 +441,7 @@ async Task GetDetails(int msg_id, int object_id, CancellationToken token, string returnByValue = true, }); - var res = await SendCommand("Runtime.evaluate", o, token); + var res = await SendCommand(msg_id, "Runtime.evaluate", o, token); //if we fail we just buble that to the IDE (and let it panic over it) if (res.IsErr) @@ -461,14 +479,13 @@ async Task GetDetails(int msg_id, int object_id, CancellationToken token, string { result = var_list }); - } catch (Exception) { - Debug ($"failed to parse {res.Value}"); + } catch (Exception e) { + Log ("verbose", $"failed to parse {res.Value} - {e.Message}"); } SendResponse(msg_id, Result.Ok(o), token); } - - async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token) + async Task GetScopeProperties (MessageId msg_id, int scope_id, CancellationToken token) { var scope = this.current_callstack.FirstOrDefault (s => s.Id == scope_id); var vars = scope.Method.GetLiveVarsAt (scope.Location.CliLocation.Offset); @@ -484,7 +501,7 @@ async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token returnByValue = true, }); - var res = await SendCommand ("Runtime.evaluate", o, token); + var res = await SendCommand (msg_id, "Runtime.evaluate", o, token); //if we fail we just buble that to the IDE (and let it panic over it) if (res.IsErr) { @@ -533,13 +550,13 @@ async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token result = var_list }); SendResponse (msg_id, Result.Ok (o), token); - } - catch (Exception) { + } catch (Exception exception) { + Log ("verbose", $"Error resolving scope properties {exception.Message}"); SendResponse (msg_id, res, token); } } - async Task EnableBreakPoint (Breakpoint bp, CancellationToken token) + async Task EnableBreakPoint (SessionId sessionId, Breakpoint bp, CancellationToken token) { var asm_name = bp.Location.CliLocation.Method.Assembly.Name; var method_token = bp.Location.CliLocation.Method.Token; @@ -553,21 +570,20 @@ async Task EnableBreakPoint (Breakpoint bp, CancellationToken token) returnByValue = true, }); - var res = await SendCommand ("Runtime.evaluate", o, token); + var res = await SendCommand (sessionId, "Runtime.evaluate", o, token); var ret_code = res.Value? ["result"]? ["value"]?.Value (); if (ret_code.HasValue) { bp.RemoteId = ret_code.Value; bp.State = BreakPointState.Active; - //Debug ($"BP local id {bp.LocalId} enabled with remote id {bp.RemoteId}"); + //Log ("verbose", $"BP local id {bp.LocalId} enabled with remote id {bp.RemoteId}"); } return res; } - async Task RuntimeReady (CancellationToken token) + async Task LoadStore (SessionId sessionId, CancellationToken token) { - var o = JObject.FromObject (new { expression = MonoCommands.GET_LOADED_FILES, objectGroup = "mono_debugger", @@ -575,10 +591,19 @@ async Task RuntimeReady (CancellationToken token) silent = false, returnByValue = true, }); - var loaded_pdbs = await SendCommand ("Runtime.evaluate", o, token); + + var loaded_pdbs = await SendCommand (sessionId, "Runtime.evaluate", o, token); var the_value = loaded_pdbs.Value? ["result"]? ["value"]; var the_pdbs = the_value?.ToObject (); - this.store = new DebugStore (the_pdbs); + + store = new DebugStore (); + await store.Load(sessionId, the_pdbs, token); + } + + async Task RuntimeReady (SessionId sessionId, CancellationToken token) + { + if (store == null) + await LoadStore (sessionId, token); foreach (var s in store.AllSources ()) { var ok = JObject.FromObject (new { @@ -587,13 +612,13 @@ async Task RuntimeReady (CancellationToken token) executionContextId = this.ctx_id, hash = s.DocHashCode, executionContextAuxData = this.aux_ctx_data, - dotNetUrl = s.DotNetUrl + dotNetUrl = s.DotNetUrl, }); - //Debug ($"\tsending {s.Url}"); - SendEvent ("Debugger.scriptParsed", ok, token); + //Log ("verbose", $"\tsending {s.Url}"); + SendEvent (sessionId, "Debugger.scriptParsed", ok, token); } - o = JObject.FromObject (new { + var o = JObject.FromObject (new { expression = MonoCommands.CLEAR_ALL_BREAKPOINTS, objectGroup = "mono_debugger", includeCommandLineAPI = false, @@ -601,9 +626,9 @@ async Task RuntimeReady (CancellationToken token) returnByValue = true, }); - var clear_result = await SendCommand ("Runtime.evaluate", o, token); + var clear_result = await SendCommand (sessionId, "Runtime.evaluate", o, token); if (clear_result.IsErr) { - Debug ($"Failed to clear breakpoints due to {clear_result}"); + Log ("verbose", $"Failed to clear breakpoints due to {clear_result}"); } @@ -612,19 +637,19 @@ async Task RuntimeReady (CancellationToken token) foreach (var bp in breakpoints) { if (bp.State != BreakPointState.Pending) continue; - var res = await EnableBreakPoint (bp, token); + var res = await EnableBreakPoint (sessionId, bp, token); var ret_code = res.Value? ["result"]? ["value"]?.Value (); //if we fail we just buble that to the IDE (and let it panic over it) if (!ret_code.HasValue) { //FIXME figure out how to inform the IDE of that. - Info ($"FAILED TO ENABLE BP {bp.LocalId}"); + Log ("info", $"FAILED TO ENABLE BP {bp.LocalId}"); bp.State = BreakPointState.Disabled; } } } - async Task RemoveBreakpoint(int msg_id, JObject args, CancellationToken token) { + async Task RemoveBreakpoint(MessageId msg_id, JObject args, CancellationToken token) { var bpid = args? ["breakpointId"]?.Value (); if (bpid?.StartsWith ("dotnet:") != true) return false; @@ -633,19 +658,19 @@ async Task RemoveBreakpoint(int msg_id, JObject args, CancellationToken to var bp = breakpoints.FirstOrDefault (b => b.LocalId == the_id); if (bp == null) { - Info ($"Could not find dotnet bp with id {the_id}"); + Log ("info", $"Could not find dotnet bp with id {the_id}"); return false; } breakpoints.Remove (bp); //FIXME verify result (and log?) - var res = await RemoveBreakPoint (bp, token); + var res = await RemoveBreakPoint (msg_id, bp, token); return true; } - async Task RemoveBreakPoint (Breakpoint bp, CancellationToken token) + async Task RemoveBreakPoint (SessionId sessionId, Breakpoint bp, CancellationToken token) { var o = JObject.FromObject (new { expression = string.Format (MonoCommands.REMOVE_BREAK_POINT, bp.RemoteId), @@ -655,7 +680,7 @@ async Task RemoveBreakPoint (Breakpoint bp, CancellationToken token) returnByValue = true, }); - var res = await SendCommand ("Runtime.evaluate", o, token); + var res = await SendCommand (sessionId, "Runtime.evaluate", o, token); var ret_code = res.Value? ["result"]? ["value"]?.Value (); if (ret_code.HasValue) { @@ -666,13 +691,13 @@ async Task RemoveBreakPoint (Breakpoint bp, CancellationToken token) return res; } - async Task SetBreakPoint (int msg_id, BreakPointRequest req, CancellationToken token) + async Task SetBreakPoint (MessageId msg_id, BreakPointRequest req, CancellationToken token) { - var bp_loc = store.FindBestBreakpoint (req); - Info ($"BP request for '{req}' runtime ready {runtime_ready} location '{bp_loc}'"); + var bp_loc = store?.FindBestBreakpoint (req); + Log ("info", $"BP request for '{req}' runtime ready {runtime_ready} location '{bp_loc}'"); if (bp_loc == null) { - Info ($"Could not resolve breakpoint request: {req}"); + Log ("info", $"Could not resolve breakpoint request: {req}"); SendResponse (msg_id, Result.Err(JObject.FromObject (new { code = (int)MonoErrorCodes.BpNotFound, message = $"C# Breakpoint at {req} not found." @@ -686,7 +711,7 @@ async Task SetBreakPoint (int msg_id, BreakPointRequest req, CancellationToken t } else { bp = new Breakpoint (bp_loc, local_breakpoint_id++, BreakPointState.Disabled); - var res = await EnableBreakPoint (bp, token); + var res = await EnableBreakPoint (msg_id, bp, token); var ret_code = res.Value? ["result"]? ["value"]?.Value (); //if we fail we just buble that to the IDE (and let it panic over it) @@ -714,7 +739,7 @@ async Task SetBreakPoint (int msg_id, BreakPointRequest req, CancellationToken t SendResponse (msg_id, Result.Ok (ok), token); } - bool GetPossibleBreakpoints (int msg_id, SourceLocation start, SourceLocation end, CancellationToken token) + bool GetPossibleBreakpoints (MessageId msg_id, SourceLocation start, SourceLocation end, CancellationToken token) { var bps = store.FindPossibleBreakpoints (start, end); if (bps == null) @@ -734,15 +759,14 @@ bool GetPossibleBreakpoints (int msg_id, SourceLocation start, SourceLocation en return true; } - void OnCompileDotnetScript (int msg_id, CancellationToken token) + void OnCompileDotnetScript (MessageId msg_id, CancellationToken token) { var o = JObject.FromObject (new { }); SendResponse (msg_id, Result.Ok (o), token); - } - async Task OnGetScriptSource (int msg_id, string script_id, CancellationToken token) + async Task OnGetScriptSource (MessageId msg_id, string script_id, CancellationToken token) { var id = new SourceId (script_id); var src_file = store.GetFileById (id); @@ -753,6 +777,16 @@ async Task OnGetScriptSource (int msg_id, string script_id, CancellationToken to try { var uri = new Uri (src_file.Url); if (uri.IsFile && File.Exists(uri.LocalPath)) { + using (var f = new StreamReader (File.Open (uri.LocalPath, FileMode.Open))) { + await res.WriteAsync (await f.ReadToEndAsync ()); + } + + var o = JObject.FromObject (new { + scriptSource = res.ToString () + }); + + SendResponse (msg_id, Result.Ok (o), token); + } else if (src_file.SourceUri.IsFile && File.Exists(src_file.SourceUri.LocalPath)) { using (var f = new StreamReader (File.Open (src_file.SourceUri.LocalPath, FileMode.Open))) { await res.WriteAsync (await f.ReadToEndAsync ()); } @@ -789,4 +823,4 @@ async Task OnGetScriptSource (int msg_id, string script_id, CancellationToken to } } } -} +} \ No newline at end of file From f54902f16973fa3f29cd782ff19ac4abe6df2c45 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Feb 2020 09:43:24 -0800 Subject: [PATCH 066/322] Purge the blazor-wasm branch --- NuGet.config | 1 + eng/Baseline.Designer.props | 436 +- eng/Baseline.xml | 154 +- eng/Dependencies.props | 10 + eng/ProjectReferences.props | 131 - eng/Versions.props | 187 +- global.json | 4 +- .../Analyzers/src/ComponentFacts.cs | 111 - ...omponentInternalUsageDiagnosticAnalzyer.cs | 43 - .../src/ComponentParameterAnalyzer.cs | 125 - .../src/ComponentParameterUsageAnalyzer.cs | 114 - ...ParametersShouldBePublicCodeFixProvider.cs | 88 - .../Analyzers/src/ComponentSymbols.cs | 79 - src/Components/Analyzers/src/ComponentsApi.cs | 32 - .../Analyzers/src/DiagnosticDescriptors.cs | 68 - .../Analyzers/src/InternalUsageAnalyzer.cs | 126 - ...oft.AspNetCore.Components.Analyzers.csproj | 23 - .../Analyzers/src/Properties/AssemblyInfo.cs | 3 - src/Components/Analyzers/src/Resources.resx | 177 - ...soft.AspNetCore.Components.Analyzers.props | 5 - .../Analyzers/test/AnalyzerTestBase.cs | 67 - ...mponentAnalyzerDiagnosticAnalyzerRunner.cs | 31 - ...nentInternalUsageDiagnoticsAnalyzerTest.cs | 60 - ...rCaptureUnmatchedValuesHasWrongTypeTest.cs | 80 - ...rCaptureUnmatchedValuesMustBeUniqueTest.cs | 69 - ...onentParameterSettersShouldBePublicTest.cs | 111 - .../ComponentParameterUsageAnalyzerTest.cs | 361 - ...metersShouldBePublicCodeFixProviderTest.cs | 126 - .../ComponentParametersShouldBePublicTest.cs | 106 - .../test/ComponentsTestDeclarations.cs | 26 - .../test/Helpers/CodeFixVerifier.Helper.cs | 90 - .../test/Helpers/DiagnosticResult.cs | 92 - .../test/Helpers/DiagnosticVerifier.Helper.cs | 175 - ...pNetCore.Components.Analyzers.Tests.csproj | 25 - .../UsesRenderTreeFrameAsParameter.cs | 11 - .../UsesRenderTreeFrameTypeAsLocal.cs | 15 - .../test/Verifiers/CodeFixVerifier.cs | 133 - .../test/Verifiers/DiagnosticVerifier.cs | 274 - ...AspNetCore.Components.Authorization.csproj | 16 - ...ore.Components.Authorization.netcoreapp.cs | 68 - ...Components.Authorization.netstandard2.0.cs | 68 - .../src/AttributeAuthorizeDataCache.cs | 41 - .../Authorization/src/AuthenticationState.cs | 28 - .../src/AuthenticationStateProvider.cs | 46 - .../Authorization/src/AuthorizeDataAdapter.cs | 39 - .../Authorization/src/AuthorizeRouteView.cs | 117 - .../Authorization/src/AuthorizeView.cs | 39 - .../Authorization/src/AuthorizeViewCore.cs | 136 - .../src/CascadingAuthenticationState.razor | 36 - ...tEnvironmentAuthenticationStateProvider.cs | 20 - ...AspNetCore.Components.Authorization.csproj | 18 - .../test/AuthorizeRouteViewTest.cs | 356 - .../Authorization/test/AuthorizeViewTest.cs | 524 - .../test/CascadingAuthenticationStateTest.cs | 207 - ...Core.Components.Authorization.Tests.csproj | 18 - .../test/TestAuthenticationStateProvider.cs | 22 - .../test/TestAuthorizationPolicyProvider.cs | 31 - .../test/TestAuthorizationService.cs | 34 - .../Authorization/test/TestIdentity.cs | 16 - src/Components/Blazor.sln | 484 + src/Components/Blazor/Blazor.sln | 440 + .../ref/Microsoft.AspNetCore.Blazor.csproj | 1 + .../src/Microsoft.AspNetCore.Blazor.csproj | 1 + ...osoft.AspNetCore.Blazor.Build.Tests.csproj | 1 + src/Components/Blazor/Directory.Build.props | 6 - src/Components/Blazor/Templates/.gitignore | 3 - src/Components/Components.sln | 1671 -- .../Components/perf/AssemblyInfo.cs | 4 - ...t.AspNetCore.Components.Performance.csproj | 16 - src/Components/Components/perf/Program.cs | 47 - .../perf/RenderTreeDiffBuilderBenchmark.cs | 114 - src/Components/Components/perf/readme.md | 35 - .../Components/ref/Directory.Build.props | 9 - .../Microsoft.AspNetCore.Components.csproj | 19 - ...rosoft.AspNetCore.Components.netcoreapp.cs | 550 - ...etCore.Components.netstandard2.0.Manual.cs | 58 - ...ft.AspNetCore.Components.netstandard2.0.cs | 550 - .../Components/src/BindConverter.cs | 1418 -- .../Components/src/BindElementAttribute.cs | 64 - .../src/CascadingParameterAttribute.cs | 27 - .../Components/src/CascadingParameterState.cs | 129 - .../Components/src/CascadingValue.cs | 184 - .../Components/src/ChangeDetection.cs | 46 - .../Components/src/ChangeEventArgs.cs | 19 - .../src/CompilerServices/RuntimeHelpers.cs | 56 - .../Components/src/ComponentBase.cs | 336 - .../Components/src/ComponentFactory.cs | 88 - src/Components/Components/src/Dispatcher.cs | 90 - .../Components/src/ElementReference.cs | 55 - .../Components/src/EventCallback.cs | 69 - .../Components/src/EventCallbackFactory.cs | 241 - .../EventCallbackFactoryBinderExtensions.cs | 539 - ...EventCallbackFactoryEventArgsExtensions.cs | 86 - .../Components/src/EventCallbackOfT.cs | 69 - .../Components/src/EventCallbackWorkItem.cs | 79 - .../Components/src/EventHandlerAttribute.cs | 68 - .../src/ICascadingValueComponent.cs | 24 - src/Components/Components/src/IComponent.cs | 31 - .../Components/src/IEventCallback.cs | 13 - .../Components/src/IHandleAfterRender.cs | 19 - src/Components/Components/src/IHandleEvent.cs | 23 - .../Components/src/InjectAttribute.cs | 16 - .../Components/src/LayoutAttribute.cs | 40 - .../Components/src/LayoutComponentBase.cs | 21 - src/Components/Components/src/LayoutView.cs | 77 - .../Components/src/LocationChangeException.cs | 23 - src/Components/Components/src/MarkupString.cs | 36 - .../Microsoft.AspNetCore.Components.csproj | 60 - ...t.AspNetCore.Components.multitarget.nuspec | 26 - ...ft.AspNetCore.Components.netcoreapp.nuspec | 20 - .../Components/src/NavigationException.cs | 26 - .../Components/src/NavigationManager.cs | 269 - .../Components/src/OwningComponentBase.cs | 100 - .../Components/src/ParameterAttribute.cs | 36 - .../Components/src/ParameterValue.cs | 35 - .../Components/src/ParameterView.cs | 375 - src/Components/Components/src/PlatformInfo.cs | 17 - .../Components/src/Properties/AssemblyInfo.cs | 9 - .../src/Reflection/ComponentProperties.cs | 288 - .../src/Reflection/IPropertySetter.cs | 12 - .../src/Reflection/MemberAssignment.cs | 87 - .../Components/src/RenderFragment.cs | 22 - src/Components/Components/src/RenderHandle.cs | 65 - .../src/RenderTree/ArrayBuilderExtensions.cs | 31 - .../src/RenderTree/ArrayBuilderSegment.cs | 67 - .../Components/src/RenderTree/ArrayRange.cs | 51 - .../src/RenderTree/EventFieldInfo.cs | 26 - .../Components/src/RenderTree/RenderBatch.cs | 52 - .../src/RenderTree/RenderTreeDiff.cs | 36 - .../src/RenderTree/RenderTreeDiffBuilder.cs | 998 -- .../src/RenderTree/RenderTreeEdit.cs | 111 - .../src/RenderTree/RenderTreeEditType.cs | 75 - .../src/RenderTree/RenderTreeFrame.cs | 406 - .../src/RenderTree/RenderTreeFrameType.cs | 66 - .../Components/src/RenderTree/Renderer.Log.cs | 66 - .../Components/src/RenderTree/Renderer.cs | 737 - .../src/RenderTree/StackObjectPool.cs | 75 - .../src/Rendering/ComponentState.cs | 218 - .../Components/src/Rendering/KeyedItemInfo.cs | 35 - .../src/Rendering/ParameterViewLifetime.cs | 31 - .../src/Rendering/RenderBatchBuilder.cs | 93 - .../src/Rendering/RenderQueueEntry.cs | 19 - .../src/Rendering/RenderTreeBuilder.cs | 773 - .../src/Rendering/RenderTreeUpdater.cs | 113 - .../RendererSynchronizationContext.cs | 312 - ...endererSynchronizationContextDispatcher.cs | 66 - .../Components/src/RouteAttribute.cs | 33 - src/Components/Components/src/RouteView.cs | 90 - .../IHostEnvironmentNavigationManager.cs | 19 - .../src/Routing/INavigationInterception.cs | 19 - .../src/Routing/LocationChangedEventArgs.cs | 34 - .../Components/src/Routing/RouteConstraint.cs | 81 - .../Components/src/Routing/RouteContext.cs | 31 - .../Components/src/Routing/RouteData.cs | 46 - .../Components/src/Routing/RouteEntry.cs | 69 - .../Components/src/Routing/RouteTable.cs | 27 - .../src/Routing/RouteTableFactory.cs | 227 - .../Components/src/Routing/RouteTemplate.cs | 22 - .../Components/src/Routing/Router.cs | 203 - .../Components/src/Routing/TemplateParser.cs | 108 - .../Components/src/Routing/TemplateSegment.cs | 66 - .../src/Routing/TypeRouteConstraint.cs | 35 - .../Components/test/BindConverterTest.cs | 307 - .../test/CascadingParameterStateTest.cs | 442 - .../Components/test/CascadingParameterTest.cs | 449 - .../Components/test/ComponentBaseTest.cs | 581 - .../Components/test/ComponentFactoryTest.cs | 168 - .../test/DependencyInjectionTest.cs | 204 - ...ventCallbackFactoryBinderExtensionsTest.cs | 713 - .../test/EventCallbackFactoryTest.cs | 654 - .../Components/test/EventCallbackTest.cs | 457 - .../Components/test/LayoutViewTest.cs | 326 - ...crosoft.AspNetCore.Components.Tests.csproj | 18 - .../Components/test/NavigationManagerTest.cs | 117 - .../test/OwningComponentBaseTest.cs | 61 - .../test/ParameterViewTest.Assignment.cs | 718 - .../Components/test/ParameterViewTest.cs | 399 - .../test/RenderTreeDiffBuilderTest.cs | 2309 --- .../Components/test/RenderTreeUpdaterTest.cs | 167 - .../Components/test/RendererTest.cs | 4500 ----- .../test/Rendering/ArrayBuilderSegmentTest.cs | 55 - .../test/Rendering/ArrayBuilderTest.cs | 334 - .../test/Rendering/RenderTreeBuilderTest.cs | 1857 --- .../RendererSynchronizationContextTest.cs | 767 - .../test/Rendering/TestArrayPool.cs | 23 - .../Components/test/RouteViewTest.cs | 209 - .../test/Routing/RouteConstraintTest.cs | 36 - .../test/Routing/RouteTableFactoryTests.cs | 504 - .../test/Routing/TemplateParserTests.cs | 187 - .../Components/test/StackObjectPoolTest.cs | 123 - src/Components/ComponentsNoDeps.slnf | 45 - src/Components/Directory.Build.props | 2 +- ...crosoft.AspNetCore.Components.Forms.csproj | 15 - ....AspNetCore.Components.Forms.netcoreapp.cs | 75 - ...NetCore.Components.Forms.netstandard2.0.cs | 75 - .../Forms/src/DataAnnotationsValidator.cs | 28 - src/Components/Forms/src/EditContext.cs | 210 - .../EditContextDataAnnotationsExtensions.cs | 107 - .../Forms/src/FieldChangedEventArgs.cs | 27 - src/Components/Forms/src/FieldIdentifier.cs | 121 - src/Components/Forms/src/FieldState.cs | 52 - ...crosoft.AspNetCore.Components.Forms.csproj | 20 - .../Forms/src/ValidationMessageStore.cs | 128 - .../Forms/src/ValidationRequestedEventArgs.cs | 25 - .../src/ValidationStateChangedEventArgs.cs | 25 - ...ditContextDataAnnotationsExtensionsTest.cs | 170 - src/Components/Forms/test/EditContextTest.cs | 240 - .../Forms/test/FieldIdentifierTest.cs | 198 - ...t.AspNetCore.Components.Forms.Tests.csproj | 17 - .../Forms/test/ValidationMessageStoreTest.cs | 96 - src/Components/Ignitor/src/BlazorClient.cs | 540 - .../Ignitor/src/CancellableOperation.cs | 78 - .../src/CapturedAttachComponentCall.cs | 17 - .../Ignitor/src/CapturedJSInteropCall.cs | 19 - .../Ignitor/src/CapturedRenderBatch.cs | 17 - src/Components/Ignitor/src/CommentNode.cs | 9 - src/Components/Ignitor/src/ComponentNode.cs | 15 - src/Components/Ignitor/src/ComponentState.cs | 18 - src/Components/Ignitor/src/ContainerNode.cs | 86 - src/Components/Ignitor/src/ElementHive.cs | 475 - src/Components/Ignitor/src/ElementNode.cs | 133 - .../Ignitor/src/ElementReference.cs | 29 - src/Components/Ignitor/src/Error.cs | 12 - src/Components/Ignitor/src/IComponent.cs | 9 - src/Components/Ignitor/src/Ignitor.csproj | 35 - .../src/IgnitorMessagePackHubProtocol.cs | 12 - src/Components/Ignitor/src/MarkupNode.cs | 15 - src/Components/Ignitor/src/Node.cs | 14 - src/Components/Ignitor/src/NodeSerializer.cs | 199 - src/Components/Ignitor/src/Operations.cs | 22 - .../Ignitor/src/Properties/AssemblyInfo.cs | 3 - .../Ignitor/src/RenderBatchReader.cs | 284 - src/Components/Ignitor/src/TextNode.cs | 15 - .../Ignitor/test/Ignitor.Test.csproj | 16 - .../Ignitor/test/RenderBatchReaderTest.cs | 321 - .../Samples/BlazorServerApp/App.razor | 10 - .../BlazorServerApp/BlazorServerApp.csproj | 18 - .../BlazorServerApp/Data/WeatherForecast.cs | 15 - .../Data/WeatherForecastService.cs | 25 - .../BlazorServerApp/Pages/Counter.razor | 16 - .../Samples/BlazorServerApp/Pages/Error.razor | 16 - .../BlazorServerApp/Pages/FetchData.razor | 46 - .../Samples/BlazorServerApp/Pages/Index.razor | 5 - .../BlazorServerApp/Pages/_Host.cshtml | 28 - .../Samples/BlazorServerApp/Program.cs | 28 - .../BlazorServerApp/Shared/MainLayout.razor | 21 - .../BlazorServerApp/Shared/NavMenu.razor | 37 - .../Samples/BlazorServerApp/Startup.cs | 60 - .../Samples/BlazorServerApp/_Imports.razor | 9 - .../appsettings.Development.json | 10 - .../Samples/BlazorServerApp/appsettings.json | 10 - .../wwwroot/css/bootstrap/bootstrap.min.css | 7 - .../css/bootstrap/bootstrap.min.css.map | 1 - .../wwwroot/css/open-iconic/FONT-LICENSE | 86 - .../wwwroot/css/open-iconic/ICON-LICENSE | 21 - .../wwwroot/css/open-iconic/README.md | 114 - .../font/css/open-iconic-bootstrap.min.css | 1 - .../open-iconic/font/fonts/open-iconic.eot | Bin 28196 -> 0 bytes .../open-iconic/font/fonts/open-iconic.otf | Bin 20996 -> 0 bytes .../open-iconic/font/fonts/open-iconic.svg | 543 - .../open-iconic/font/fonts/open-iconic.ttf | Bin 28028 -> 0 bytes .../open-iconic/font/fonts/open-iconic.woff | Bin 14984 -> 0 bytes .../BlazorServerApp/wwwroot/css/site.css | 183 - .../BlazorServerApp/wwwroot/favicon.ico | Bin 32038 -> 0 bytes ...rosoft.AspNetCore.Components.Server.csproj | 18 - ...AspNetCore.Components.Server.netcoreapp.cs | 77 - .../src/BlazorPack/ArrayBufferWriter.cs | 193 - .../src/BlazorPack/BlazorPackHubProtocol.cs | 655 - .../NonDefaultHubProtocolAttribute.cs | 13 - .../Server/src/BlazorPack/Requires.cs | 35 - .../Server/src/BlazorPack/SequenceOfT.cs | 451 - .../ComponentEndpointConventionBuilder.cs | 32 - ...ComponentEndpointRouteBuilderExtensions.cs | 115 - .../Server/src/CircuitDisconnectMiddleware.cs | 109 - src/Components/Server/src/CircuitOptions.cs | 80 - .../src/Circuits/ArrayBuilderMemoryStream.cs | 126 - src/Components/Server/src/Circuits/Circuit.cs | 23 - .../Server/src/Circuits/CircuitClientProxy.cs | 51 - .../Server/src/Circuits/CircuitFactory.cs | 101 - .../Server/src/Circuits/CircuitHandle.cs | 14 - .../Server/src/Circuits/CircuitHandler.cs | 79 - .../Server/src/Circuits/CircuitHost.cs | 865 - .../Server/src/Circuits/CircuitId.cs | 63 - .../Server/src/Circuits/CircuitIdFactory.cs | 91 - ...onsJSInteropDetailedErrorsConfiguration.cs | 24 - .../Server/src/Circuits/CircuitRegistry.cs | 525 - .../src/Circuits/ComponentDescriptor.cs | 19 - .../ComponentParameterDeserializer.cs | 188 - .../Circuits/ComponentParametersTypeCache.cs | 58 - .../src/Circuits/DefaultCircuitAccessor.cs | 10 - .../Server/src/Circuits/ICircuitAccessor.cs | 10 - .../Server/src/Circuits/RemoteJSRuntime.cs | 148 - .../Circuits/RemoteNavigationInterception.cs | 43 - .../src/Circuits/RemoteNavigationManager.cs | 100 - .../Server/src/Circuits/RemoteRenderer.cs | 502 - .../Server/src/Circuits/RenderBatchWriter.cs | 307 - ...datingServerAuthenticationStateProvider.cs | 120 - .../ServerAuthenticationStateProvider.cs | 29 - .../Circuits/ServerComponentDeserializer.cs | 280 - .../src/Circuits/ServerComponentTypeCache.cs | 59 - src/Components/Server/src/ComponentHub.cs | 342 - .../ComponentServiceCollectionExtensions.cs | 98 - .../ConfigureStaticFilesOptions.cs | 66 - .../IServerSideBlazorBuilder.cs | 16 - .../ServerSideBlazorBuilderExtensions.cs | 59 - ...rosoft.AspNetCore.Components.Server.csproj | 87 - .../Server/src/Properties/AssemblyInfo.cs | 8 - .../BlazorPack/BlazorPackHubProtocolTest.cs | 13 - .../test/CircuitDisconnectMiddlewareTest.cs | 244 - .../test/Circuits/CircuitClientProxyTest.cs | 53 - .../Server/test/Circuits/CircuitHostTest.cs | 306 - .../test/Circuits/CircuitIdFactoryTest.cs | 92 - .../test/Circuits/CircuitRegistryTest.cs | 407 - .../test/Circuits/RemoteRendererTest.cs | 535 - .../test/Circuits/RenderBatchWriterTest.cs | 399 - ...datingServerAuthenticationStateProvider.cs | 257 - .../ServerAuthenticationStateProviderTest.cs | 50 - .../ServerComponentDeserializerTest.cs | 378 - .../Server/test/Circuits/TestCircuitHost.cs | 57 - .../test/Circuits/TestCircuitIdFactory.cs | 15 - ...onentEndpointRouteBuilderExtensionsTest.cs | 87 - ...omponentServiceCollectionExtensionsTest.cs | 82 - .../test/ElementReferenceJsonConverterTest.cs | 108 - ....AspNetCore.Components.Server.Tests.csproj | 26 - ...Microsoft.AspNetCore.Components.Web.csproj | 20 - ...ft.AspNetCore.Components.Web.netcoreapp.cs | 435 - ...spNetCore.Components.Web.netstandard2.0.cs | 435 - .../Web/src/BindInputElementAttribute.cs | 79 - .../Forms/EditContextFieldClassExtensions.cs | 46 - src/Components/Web/src/Forms/EditForm.cs | 144 - src/Components/Web/src/Forms/InputBase.cs | 237 - src/Components/Web/src/Forms/InputCheckbox.cs | 39 - src/Components/Web/src/Forms/InputDate.cs | 112 - src/Components/Web/src/Forms/InputNumber.cs | 103 - src/Components/Web/src/Forms/InputSelect.cs | 61 - src/Components/Web/src/Forms/InputText.cs | 41 - src/Components/Web/src/Forms/InputTextArea.cs | 41 - .../Web/src/Forms/ValidationMessage.cs | 106 - .../Web/src/Forms/ValidationSummary.cs | 118 - ...Microsoft.AspNetCore.Components.Web.csproj | 20 - .../Web/src/Properties/AssemblyInfo.cs | 3 - src/Components/Web/src/Routing/NavLink.cs | 195 - .../Web/src/Routing/NavLinkMatch.cs | 23 - src/Components/Web/src/Web/BindAttributes.cs | 52 - .../Web/src/Web/ClipboardEventArgs.cs | 18 - src/Components/Web/src/Web/DataTransfer.cs | 41 - .../Web/src/Web/DataTransferItem.cs | 23 - src/Components/Web/src/Web/DragEventArgs.cs | 17 - src/Components/Web/src/Web/ErrorEventArgs.cs | 38 - src/Components/Web/src/Web/EventHandlers.cs | 128 - src/Components/Web/src/Web/FocusEventArgs.cs | 21 - .../Web/src/Web/KeyboardEventArgs.cs | 62 - src/Components/Web/src/Web/MouseEventArgs.cs | 84 - .../Web/src/Web/PointerEventArgs.cs | 55 - .../Web/src/Web/ProgressEventArgs.cs | 35 - src/Components/Web/src/Web/TouchEventArgs.cs | 61 - src/Components/Web/src/Web/TouchPoint.cs | 51 - ...EventCallbackFactoryEventArgsExtensions.cs | 373 - .../src/Web/WebRenderTreeBuilderExtensions.cs | 53 - src/Components/Web/src/Web/WheelEventArgs.cs | 31 - src/Components/Web/src/WebEventDescriptor.cs | 37 - .../Web/test/Forms/InputBaseTest.cs | 513 - ...oft.AspNetCore.Components.Web.Tests.csproj | 19 - ...soft.AspNetCore.Components.E2ETests.csproj | 6 +- .../ComponentsApp.App.csproj | 3 +- .../ComponentsApp.Server.csproj | 4 +- .../TestServer/Components.TestServer.csproj | 2 - ...oft.DotNet.Web.Client.ItemTemplates.csproj | 9 - .../Less/.template.config/dotnetcli.host.json | 3 - .../Less/.template.config/template.json | 40 - .../content/Less/styleSheet1.less | 2 - .../Scss/.template.config/dotnetcli.host.json | 3 - .../Scss/.template.config/template.json | 40 - .../content/Scss/styleSheet1.scss | 2 - .../.template.config/dotnetcli.host.json | 3 - .../TypeScript/.template.config/template.json | 40 - .../content/TypeScript/file1.ts | 1 - .../Microsoft.DotNet.Web.ItemTemplates.csproj | 9 - .../.template.config/dotnetcli.host.json | 3 - .../Protobuf/.template.config/template.json | 49 - .../content/Protobuf/protobuf.proto | 3 - .../.template.config/dotnetcli.host.json | 3 - .../.template.config/template.json | 44 - .../content/RazorComponent/Component1.razor | 5 - .../.template.config/dotnetcli.host.json | 3 - .../RazorPage/.template.config/template.json | 70 - .../content/RazorPage/Index.cshtml | 6 - .../content/RazorPage/Index.cshtml.cs | 20 - .../.template.config/dotnetcli.host.json | 3 - .../.template.config/template.json | 46 - .../content/ViewImports/_ViewImports.cshtml | 2 - .../.template.config/dotnetcli.host.json | 3 - .../ViewStart/.template.config/template.json | 41 - .../content/ViewStart/_ViewStart.cshtml | 3 - .../Web.ProjectTemplates/.gitignore | 3 - .../BlazorServerWeb-CSharp.csproj.in | 31 - .../EmptyWeb-CSharp.csproj.in | 9 - .../EmptyWeb-FSharp.fsproj.in | 14 - .../GrpcService-CSharp.csproj.in | 15 - ...crosoft.DotNet.Web.ProjectTemplates.csproj | 51 - .../RazorClassLibrary-CSharp.csproj.in | 20 - .../RazorPagesWeb-CSharp.csproj.in | 32 - .../StarterWeb-CSharp.csproj.in | 32 - .../StarterWeb-FSharp.fsproj.in | 20 - .../WebApi-CSharp.csproj.in | 19 - .../WebApi-FSharp.fsproj.in | 16 - .../Worker-CSharp.csproj.in | 13 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 75 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 381 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 66 - .../.template.config/vs-2017.3/icon.png | Bin 1157 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/BlazorServerWeb-CSharp/App.razor | 25 - .../Identity/Pages/Account/LogOut.cshtml | 15 - .../Pages/Shared/_LoginPartial.cshtml | 27 - ...tingIdentityAuthenticationStateProvider.cs | 75 - .../Data/ApplicationDbContext.cs | 16 - ...000000000_CreateIdentitySchema.Designer.cs | 270 - .../00000000000000_CreateIdentitySchema.cs | 217 - .../ApplicationDbContextModelSnapshot.cs | 268 - ...000000000_CreateIdentitySchema.Designer.cs | 277 - .../00000000000000_CreateIdentitySchema.cs | 220 - .../ApplicationDbContextModelSnapshot.cs | 275 - .../Data/WeatherForecast.cs | 15 - .../Data/WeatherForecastService.cs | 25 - .../Pages/Counter.razor | 16 - .../BlazorServerWeb-CSharp/Pages/Error.razor | 16 - .../Pages/FetchData.razor | 46 - .../BlazorServerWeb-CSharp/Pages/Index.razor | 5 - .../BlazorServerWeb-CSharp/Pages/_Host.cshtml | 36 - .../content/BlazorServerWeb-CSharp/Program.cs | 28 - .../Properties/launchSettings.json | 40 - .../LoginDisplay.IndividualB2CAuth.razor | 30 - .../LoginDisplay.IndividualLocalAuth.razor | 12 - .../LoginDisplay.OrganizationalAuth.razor | 9 - .../Shared/LoginDisplay.WindowsAuth.razor | 3 - .../Shared/MainLayout.Auth.razor | 16 - .../Shared/MainLayout.NoAuth.razor | 15 - .../Shared/NavMenu.razor | 37 - .../content/BlazorServerWeb-CSharp/Startup.cs | 178 - .../BlazorServerWeb-CSharp/_Imports.razor | 9 - .../content/BlazorServerWeb-CSharp/app.db | Bin 106496 -> 0 bytes .../appsettings.Development.json | 10 - .../BlazorServerWeb-CSharp/appsettings.json | 42 - .../wwwroot/css/bootstrap/bootstrap.min.css | 7 - .../css/bootstrap/bootstrap.min.css.map | 1 - .../wwwroot/css/open-iconic/FONT-LICENSE | 86 - .../wwwroot/css/open-iconic/ICON-LICENSE | 21 - .../wwwroot/css/open-iconic/README.md | 114 - .../font/css/open-iconic-bootstrap.min.css | 1 - .../open-iconic/font/fonts/open-iconic.eot | Bin 28196 -> 0 bytes .../open-iconic/font/fonts/open-iconic.otf | Bin 20996 -> 0 bytes .../open-iconic/font/fonts/open-iconic.svg | 543 - .../open-iconic/font/fonts/open-iconic.ttf | Bin 28028 -> 0 bytes .../open-iconic/font/fonts/open-iconic.woff | Bin 14984 -> 0 bytes .../wwwroot/css/site.css | 183 - .../wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../content/Directory.Build.props | 8 - .../content/Directory.Build.targets | 7 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 29 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 136 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 39 - .../.template.config/vs-2017.3/Empty.png | Bin 303 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/EmptyWeb-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 40 - .../content/EmptyWeb-CSharp/Startup.cs | 40 - .../appsettings.Development.json | 9 - .../content/EmptyWeb-CSharp/appsettings.json | 10 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 29 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 132 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 37 - .../.template.config/vs-2017.3/Empty.png | Bin 303 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/EmptyWeb-FSharp/Program.fs | 27 - .../Properties/launchSettings.json | 35 - .../content/EmptyWeb-FSharp/Startup.fs | 26 - .../appsettings.Development.json | 9 - .../content/EmptyWeb-FSharp/appsettings.json | 10 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 16 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 82 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 19 - .../.template.config/vs-2017.3/gRPC.png | Bin 678 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/GrpcService-CSharp/Program.cs | 27 - .../Properties/launchSettings.json | 12 - .../GrpcService-CSharp/Protos/greet.proto | 21 - .../Services/GreeterService.cs | 26 - .../content/GrpcService-CSharp/Startup.cs | 43 - .../appsettings.Development.json | 10 - .../GrpcService-CSharp/appsettings.json | 15 - .../.template.config/cs-CZ/strings.json | 8 - .../.template.config/de-DE/strings.json | 8 - .../.template.config/dotnetcli.host.json | 17 - .../.template.config/en/strings.json | 8 - .../.template.config/es-ES/strings.json | 8 - .../.template.config/fr-FR/strings.json | 8 - .../.template.config/it-IT/strings.json | 8 - .../.template.config/ja-JP/strings.json | 8 - .../.template.config/ko-KR/strings.json | 8 - .../.template.config/pl-PL/strings.json | 8 - .../.template.config/pt-BR/strings.json | 8 - .../.template.config/ru-RU/strings.json | 8 - .../.template.config/template.json | 107 - .../.template.config/tr-TR/strings.json | 8 - .../.template.config/vs-2017.3.host.json | 25 - .../vs-2017.3/RazorClassLibrary.ico | Bin 42890 -> 0 bytes .../.template.config/zh-CN/strings.json | 8 - .../.template.config/zh-TW/strings.json | 8 - .../Areas/MyFeature/Pages/Page1.cshtml | 13 - .../Areas/MyFeature/Pages/Page1.cshtml.cs | 17 - .../RazorClassLibrary-CSharp/Component1.razor | 3 - .../ExampleJsInterop.cs | 16 - .../RazorClassLibrary-CSharp/_Imports.razor | 1 - .../wwwroot/background.png | Bin 378 -> 0 bytes .../wwwroot/exampleJsInterop.js | 8 - .../wwwroot/styles.css | 11 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 75 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 348 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 66 - .../vs-2017.3/WebApplication.png | Bin 1196 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../Areas/Identity/Pages/_ViewStart.cshtml | 3 - .../Data/ApplicationDbContext.cs | 16 - ...000000000_CreateIdentitySchema.Designer.cs | 270 - .../00000000000000_CreateIdentitySchema.cs | 217 - .../ApplicationDbContextModelSnapshot.cs | 268 - ...000000000_CreateIdentitySchema.Designer.cs | 277 - .../00000000000000_CreateIdentitySchema.cs | 220 - .../ApplicationDbContextModelSnapshot.cs | 275 - .../RazorPagesWeb-CSharp/Pages/Error.cshtml | 26 - .../Pages/Error.cshtml.cs | 31 - .../RazorPagesWeb-CSharp/Pages/Index.cshtml | 10 - .../Pages/Index.cshtml.cs | 25 - .../RazorPagesWeb-CSharp/Pages/Privacy.cshtml | 8 - .../Pages/Privacy.cshtml.cs | 24 - .../Pages/Shared/_Layout.cshtml | 55 - .../Shared/_LoginPartial.Identity.cshtml | 26 - .../Pages/Shared/_LoginPartial.OrgAuth.cshtml | 57 - .../Shared/_ValidationScriptsPartial.cshtml | 2 - .../Pages/_ViewImports.cshtml | 9 - .../Pages/_ViewStart.cshtml | 3 - .../content/RazorPagesWeb-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 40 - .../content/RazorPagesWeb-CSharp/Startup.cs | 165 - .../content/RazorPagesWeb-CSharp/app.db | Bin 106496 -> 0 bytes .../appsettings.Development.json | 9 - .../RazorPagesWeb-CSharp/appsettings.json | 42 - .../RazorPagesWeb-CSharp/wwwroot/css/site.css | 71 - .../RazorPagesWeb-CSharp/wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../RazorPagesWeb-CSharp/wwwroot/js/site.js | 4 - .../wwwroot/lib/bootstrap/LICENSE | 22 - .../lib/bootstrap/dist/css/bootstrap-grid.css | 3719 ----- .../bootstrap/dist/css/bootstrap-grid.css.map | 1 - .../bootstrap/dist/css/bootstrap-grid.min.css | 7 - .../dist/css/bootstrap-grid.min.css.map | 1 - .../bootstrap/dist/css/bootstrap-reboot.css | 331 - .../dist/css/bootstrap-reboot.css.map | 1 - .../dist/css/bootstrap-reboot.min.css | 8 - .../dist/css/bootstrap-reboot.min.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.css | 10038 ----------- .../lib/bootstrap/dist/css/bootstrap.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.min.css | 7 - .../bootstrap/dist/css/bootstrap.min.css.map | 1 - .../lib/bootstrap/dist/js/bootstrap.bundle.js | 7013 -------- .../bootstrap/dist/js/bootstrap.bundle.js.map | 1 - .../bootstrap/dist/js/bootstrap.bundle.min.js | 7 - .../dist/js/bootstrap.bundle.min.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.js | 4435 ----- .../lib/bootstrap/dist/js/bootstrap.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.min.js | 7 - .../bootstrap/dist/js/bootstrap.min.js.map | 1 - .../jquery-validation-unobtrusive/LICENSE.txt | 12 - .../jquery.validate.unobtrusive.js | 432 - .../jquery.validate.unobtrusive.min.js | 5 - .../wwwroot/lib/jquery-validation/LICENSE.md | 22 - .../dist/additional-methods.js | 1158 -- .../dist/additional-methods.min.js | 4 - .../jquery-validation/dist/jquery.validate.js | 1601 -- .../dist/jquery.validate.min.js | 4 - .../wwwroot/lib/jquery/LICENSE.txt | 36 - .../wwwroot/lib/jquery/dist/jquery.js | 10364 ------------ .../wwwroot/lib/jquery/dist/jquery.min.js | 2 - .../wwwroot/lib/jquery/dist/jquery.min.map | 1 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 75 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 344 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 66 - .../vs-2017.3/WebApplication.png | Bin 1196 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../Areas/Identity/Pages/_ViewStart.cshtml | 3 - .../Controllers/HomeController.cs | 46 - .../Data/ApplicationDbContext.cs | 16 - ...000000000_CreateIdentitySchema.Designer.cs | 270 - .../00000000000000_CreateIdentitySchema.cs | 217 - .../ApplicationDbContextModelSnapshot.cs | 268 - ...000000000_CreateIdentitySchema.Designer.cs | 277 - .../00000000000000_CreateIdentitySchema.cs | 220 - .../ApplicationDbContextModelSnapshot.cs | 275 - .../Models/ErrorViewModel.cs | 11 - .../content/StarterWeb-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 40 - .../content/StarterWeb-CSharp/Startup.cs | 168 - .../StarterWeb-CSharp/Views/Home/Index.cshtml | 8 - .../Views/Home/Privacy.cshtml | 6 - .../Views/Shared/Error.cshtml | 25 - .../Views/Shared/_Layout.cshtml | 53 - .../Shared/_LoginPartial.Identity.cshtml | 26 - .../Views/Shared/_LoginPartial.OrgAuth.cshtml | 58 - .../Shared/_ValidationScriptsPartial.cshtml | 2 - .../Views/_ViewImports.cshtml | 3 - .../StarterWeb-CSharp/Views/_ViewStart.cshtml | 3 - .../content/StarterWeb-CSharp/app.db | Bin 106496 -> 0 bytes .../appsettings.Development.json | 9 - .../StarterWeb-CSharp/appsettings.json | 42 - .../StarterWeb-CSharp/wwwroot/css/site.css | 71 - .../StarterWeb-CSharp/wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../StarterWeb-CSharp/wwwroot/js/site.js | 4 - .../wwwroot/lib/bootstrap/LICENSE | 22 - .../lib/bootstrap/dist/css/bootstrap-grid.css | 3719 ----- .../bootstrap/dist/css/bootstrap-grid.css.map | 1 - .../bootstrap/dist/css/bootstrap-grid.min.css | 7 - .../dist/css/bootstrap-grid.min.css.map | 1 - .../bootstrap/dist/css/bootstrap-reboot.css | 331 - .../dist/css/bootstrap-reboot.css.map | 1 - .../dist/css/bootstrap-reboot.min.css | 8 - .../dist/css/bootstrap-reboot.min.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.css | 10038 ----------- .../lib/bootstrap/dist/css/bootstrap.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.min.css | 7 - .../bootstrap/dist/css/bootstrap.min.css.map | 1 - .../lib/bootstrap/dist/js/bootstrap.bundle.js | 7013 -------- .../bootstrap/dist/js/bootstrap.bundle.js.map | 1 - .../bootstrap/dist/js/bootstrap.bundle.min.js | 7 - .../dist/js/bootstrap.bundle.min.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.js | 4435 ----- .../lib/bootstrap/dist/js/bootstrap.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.min.js | 7 - .../bootstrap/dist/js/bootstrap.min.js.map | 1 - .../jquery-validation-unobtrusive/LICENSE.txt | 12 - .../jquery.validate.unobtrusive.js | 432 - .../jquery.validate.unobtrusive.min.js | 5 - .../wwwroot/lib/jquery-validation/LICENSE.md | 22 - .../dist/additional-methods.js | 1158 -- .../dist/additional-methods.min.js | 4 - .../jquery-validation/dist/jquery.validate.js | 1601 -- .../dist/jquery.validate.min.js | 4 - .../wwwroot/lib/jquery/LICENSE.txt | 36 - .../wwwroot/lib/jquery/dist/jquery.js | 10364 ------------ .../wwwroot/lib/jquery/dist/jquery.min.js | 2 - .../wwwroot/lib/jquery/dist/jquery.min.map | 1 - .../.template.config/dotnetcli.host.json | 29 - .../.template.config/template.json | 137 - .../Controllers/HomeController.fs | 20 - .../Models/ErrorViewModel.fs | 8 - .../content/StarterWeb-FSharp/Program.fs | 27 - .../Properties/launchSettings.json | 40 - .../content/StarterWeb-FSharp/Startup.fs | 55 - .../StarterWeb-FSharp/Views/Home/Index.cshtml | 8 - .../Views/Home/Privacy.cshtml | 6 - .../Views/Shared/Error.cshtml | 25 - .../Views/Shared/_Layout.cshtml | 52 - .../Shared/_ValidationScriptsPartial.cshtml | 3 - .../Views/_ViewImports.cshtml | 2 - .../StarterWeb-FSharp/Views/_ViewStart.cshtml | 3 - .../appsettings.Development.json | 9 - .../StarterWeb-FSharp/appsettings.json | 10 - .../StarterWeb-FSharp/wwwroot/css/site.css | 71 - .../StarterWeb-FSharp/wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../StarterWeb-FSharp/wwwroot/js/site.js | 4 - .../wwwroot/lib/bootstrap/LICENSE | 22 - .../lib/bootstrap/dist/css/bootstrap-grid.css | 3719 ----- .../bootstrap/dist/css/bootstrap-grid.css.map | 1 - .../bootstrap/dist/css/bootstrap-grid.min.css | 7 - .../dist/css/bootstrap-grid.min.css.map | 1 - .../bootstrap/dist/css/bootstrap-reboot.css | 331 - .../dist/css/bootstrap-reboot.css.map | 1 - .../dist/css/bootstrap-reboot.min.css | 8 - .../dist/css/bootstrap-reboot.min.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.css | 10038 ----------- .../lib/bootstrap/dist/css/bootstrap.css.map | 1 - .../lib/bootstrap/dist/css/bootstrap.min.css | 7 - .../bootstrap/dist/css/bootstrap.min.css.map | 1 - .../lib/bootstrap/dist/js/bootstrap.bundle.js | 7013 -------- .../bootstrap/dist/js/bootstrap.bundle.js.map | 1 - .../bootstrap/dist/js/bootstrap.bundle.min.js | 7 - .../dist/js/bootstrap.bundle.min.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.js | 4435 ----- .../lib/bootstrap/dist/js/bootstrap.js.map | 1 - .../lib/bootstrap/dist/js/bootstrap.min.js | 7 - .../bootstrap/dist/js/bootstrap.min.js.map | 1 - .../jquery-validation-unobtrusive/LICENSE.txt | 12 - .../jquery.validate.unobtrusive.js | 432 - .../jquery.validate.unobtrusive.min.js | 5 - .../wwwroot/lib/jquery-validation/LICENSE.md | 22 - .../dist/additional-methods.js | 1158 -- .../dist/additional-methods.min.js | 4 - .../jquery-validation/dist/jquery.validate.js | 1601 -- .../dist/jquery.validate.min.js | 4 - .../wwwroot/lib/jquery/LICENSE.txt | 36 - .../wwwroot/lib/jquery/dist/jquery.js | 10364 ------------ .../wwwroot/lib/jquery/dist/jquery.min.js | 2 - .../wwwroot/lib/jquery/dist/jquery.min.map | 1 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 63 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 253 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 56 - .../.template.config/vs-2017.3/WebAPI.png | Bin 523 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../Controllers/WeatherForecastController.cs | 45 - .../content/WebApi-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 43 - .../content/WebApi-CSharp/Startup.cs | 74 - .../content/WebApi-CSharp/WeatherForecast.cs | 15 - .../appsettings.Development.json | 9 - .../content/WebApi-CSharp/appsettings.json | 29 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 29 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 132 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 39 - .../.template.config/vs-2017.3/WebAPI.png | Bin 523 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../Controllers/WeatherForecastController.fs | 26 - .../content/WebApi-FSharp/Program.fs | 27 - .../Properties/launchSettings.json | 43 - .../content/WebApi-FSharp/Startup.fs | 45 - .../content/WebApi-FSharp/WeatherForecast.fs | 11 - .../appsettings.Development.json | 9 - .../content/WebApi-FSharp/appsettings.json | 10 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 19 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 91 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 20 - .../.template.config/vs-2017.3/Worker.png | Bin 230 -> 0 bytes .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/Worker-CSharp/Program.cs | 24 - .../Properties/launchSettings.json | 10 - .../content/Worker-CSharp/Worker.cs | 29 - .../appsettings.Development.json | 9 - .../content/Worker-CSharp/appsettings.json | 9 - .../Web.Spa.ProjectTemplates/.gitignore | 2 - .../Angular-CSharp.csproj.in | 69 - ...oft.DotNet.Web.Spa.ProjectTemplates.csproj | 39 - .../React-CSharp.csproj.in | 64 - .../ReactRedux-CSharp.csproj.in | 53 - .../content/Angular-CSharp/.gitignore | 231 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 35 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../Angular-CSharp/.template.config/icon.png | Bin 1833 -> 0 bytes .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 209 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 44 - .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../Angular-CSharp/ClientApp/.editorconfig | 13 - .../Angular-CSharp/ClientApp/.gitignore | 40 - .../Angular-CSharp/ClientApp/README.md | 27 - .../Angular-CSharp/ClientApp/angular.json | 136 - .../Angular-CSharp/ClientApp/browserslist | 9 - .../ClientApp/e2e/protractor.conf.js | 28 - .../ClientApp/e2e/src/app.e2e-spec.ts | 14 - .../ClientApp/e2e/src/app.po.ts | 11 - .../ClientApp/e2e/tsconfig.e2e.json | 13 - .../ClientApp/package-lock.json | 13670 --------------- .../Angular-CSharp/ClientApp/package.json | 58 - .../api-authorization.constants.ts | 81 - .../api-authorization.module.spec.ts | 13 - .../api-authorization.module.ts | 30 - .../api-authorization/authorize.guard.spec.ts | 15 - .../src/api-authorization/authorize.guard.ts | 30 - .../authorize.interceptor.spec.ts | 15 - .../authorize.interceptor.ts | 54 - .../authorize.service.spec.ts | 15 - .../api-authorization/authorize.service.ts | 199 - .../login-menu/login-menu.component.css | 0 .../login-menu/login-menu.component.html | 16 - .../login-menu/login-menu.component.spec.ts | 25 - .../login-menu/login-menu.component.ts | 21 - .../login/login.component.css | 0 .../login/login.component.html | 1 - .../login/login.component.spec.ts | 25 - .../login/login.component.ts | 128 - .../logout/logout.component.css | 0 .../logout/logout.component.html | 1 - .../logout/logout.component.spec.ts | 25 - .../logout/logout.component.ts | 114 - .../ClientApp/src/app/app.component.html | 6 - .../ClientApp/src/app/app.component.ts | 9 - .../ClientApp/src/app/app.module.ts | 52 - .../ClientApp/src/app/app.server.module.ts | 11 - .../src/app/counter/counter.component.html | 7 - .../src/app/counter/counter.component.spec.ts | 36 - .../src/app/counter/counter.component.ts | 13 - .../app/fetch-data/fetch-data.component.html | 24 - .../app/fetch-data/fetch-data.component.ts | 23 - .../src/app/home/home.component.html | 14 - .../ClientApp/src/app/home/home.component.ts | 8 - .../src/app/nav-menu/nav-menu.component.css | 18 - .../src/app/nav-menu/nav-menu.component.html | 47 - .../src/app/nav-menu/nav-menu.component.ts | 18 - .../ClientApp/src/assets/.gitkeep | 0 .../src/environments/environment.prod.ts | 3 - .../ClientApp/src/environments/environment.ts | 15 - .../Angular-CSharp/ClientApp/src/index.html | 14 - .../ClientApp/src/karma.conf.js | 31 - .../Angular-CSharp/ClientApp/src/main.ts | 20 - .../Angular-CSharp/ClientApp/src/polyfills.ts | 63 - .../Angular-CSharp/ClientApp/src/styles.css | 16 - .../Angular-CSharp/ClientApp/src/test.ts | 20 - .../ClientApp/src/tsconfig.app.json | 11 - .../ClientApp/src/tsconfig.server.json | 9 - .../ClientApp/src/tsconfig.spec.json | 18 - .../Angular-CSharp/ClientApp/src/tslint.json | 17 - .../Angular-CSharp/ClientApp/tsconfig.json | 21 - .../Angular-CSharp/ClientApp/tslint.json | 130 - .../OidcConfigurationController.cs | 26 - .../Controllers/WeatherForecastController.cs | 45 - .../Data/ApplicationDbContext.cs | 21 - ...000000000_CreateIdentitySchema.Designer.cs | 359 - .../00000000000000_CreateIdentitySchema.cs | 280 - .../ApplicationDbContextModelSnapshot.cs | 357 - ...000000000_CreateIdentitySchema.Designer.cs | 352 - .../00000000000000_CreateIdentitySchema.cs | 278 - .../ApplicationDbContextModelSnapshot.cs | 350 - .../Angular-CSharp/Models/ApplicationUser.cs | 12 - .../content/Angular-CSharp/Pages/Error.cshtml | 26 - .../Angular-CSharp/Pages/Error.cshtml.cs | 31 - .../Pages/Shared/_LoginPartial.cshtml | 36 - .../Angular-CSharp/Pages/_ViewImports.cshtml | 3 - .../content/Angular-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 35 - .../content/Angular-CSharp/Startup.cs | 129 - .../content/Angular-CSharp/WeatherForecast.cs | 15 - .../content/Angular-CSharp/app.db | Bin 135168 -> 0 bytes .../appsettings.Development.json | 18 - .../content/Angular-CSharp/appsettings.json | 28 - .../Angular-CSharp/wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../content/Directory.Build.props | 8 - .../content/Directory.Build.targets | 7 - .../content/React-CSharp/.gitignore | 232 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 35 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../React-CSharp/.template.config/icon.png | Bin 2431 -> 0 bytes .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 210 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 44 - .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../content/React-CSharp/ClientApp/.gitignore | 21 - .../content/React-CSharp/ClientApp/README.md | 2228 --- .../React-CSharp/ClientApp/package-lock.json | 12820 -------------- .../React-CSharp/ClientApp/package.json | 40 - .../React-CSharp/ClientApp/public/favicon.ico | Bin 32038 -> 0 bytes .../React-CSharp/ClientApp/public/index.html | 41 - .../ClientApp/public/manifest.json | 15 - .../content/React-CSharp/ClientApp/src/App.js | 33 - .../React-CSharp/ClientApp/src/App.test.js | 13 - .../ClientApp/src/components/Counter.js | 31 - .../ClientApp/src/components/FetchData.js | 71 - .../ClientApp/src/components/Home.js | 26 - .../ClientApp/src/components/Layout.js | 18 - .../ClientApp/src/components/NavMenu.css | 18 - .../ClientApp/src/components/NavMenu.js | 56 - .../ApiAuthorizationConstants.js | 38 - .../ApiAuthorizationRoutes.js | 30 - .../api-authorization/AuthorizeRoute.js | 53 - .../api-authorization/AuthorizeService.js | 213 - .../src/components/api-authorization/Login.js | 133 - .../components/api-authorization/LoginMenu.js | 69 - .../components/api-authorization/Logout.js | 128 - .../React-CSharp/ClientApp/src/custom.css | 14 - .../React-CSharp/ClientApp/src/index.js | 33 - .../ClientApp/src/registerServiceWorker.js | 108 - .../React-CSharp/ClientApp/src/setupTests.js | 23 - .../OidcConfigurationController.cs | 26 - .../Controllers/WeatherForecastController.cs | 45 - .../React-CSharp/Data/ApplicationDbContext.cs | 21 - ...000000000_CreateIdentitySchema.Designer.cs | 359 - .../00000000000000_CreateIdentitySchema.cs | 280 - .../ApplicationDbContextModelSnapshot.cs | 357 - ...000000000_CreateIdentitySchema.Designer.cs | 352 - .../00000000000000_CreateIdentitySchema.cs | 278 - .../ApplicationDbContextModelSnapshot.cs | 350 - .../React-CSharp/Models/ApplicationUser.cs | 12 - .../content/React-CSharp/Pages/Error.cshtml | 26 - .../React-CSharp/Pages/Error.cshtml.cs | 31 - .../Pages/Shared/_LoginPartial.cshtml | 36 - .../React-CSharp/Pages/_ViewImports.cshtml | 3 - .../content/React-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 35 - .../content/React-CSharp/Startup.cs | 125 - .../content/React-CSharp/WeatherForecast.cs | 15 - .../content/React-CSharp/app.db | Bin 135168 -> 0 bytes .../React-CSharp/appsettings.Development.json | 18 - .../content/React-CSharp/appsettings.json | 28 - .../content/ReactRedux-CSharp/.gitignore | 232 - .../.template.config/cs-CZ/strings.json | 7 - .../.template.config/de-DE/strings.json | 7 - .../.template.config/dotnetcli.host.json | 26 - .../.template.config/en/strings.json | 7 - .../.template.config/es-ES/strings.json | 7 - .../.template.config/fr-FR/strings.json | 7 - .../.template.config/icon.png | Bin 2876 -> 0 bytes .../.template.config/it-IT/strings.json | 7 - .../.template.config/ja-JP/strings.json | 7 - .../.template.config/ko-KR/strings.json | 7 - .../.template.config/pl-PL/strings.json | 7 - .../.template.config/pt-BR/strings.json | 7 - .../.template.config/ru-RU/strings.json | 7 - .../.template.config/template.json | 131 - .../.template.config/tr-TR/strings.json | 7 - .../.template.config/vs-2017.3.host.json | 39 - .../.template.config/zh-CN/strings.json | 7 - .../.template.config/zh-TW/strings.json | 7 - .../ClientApp/.eslintrc.json | 7 - .../ReactRedux-CSharp/ClientApp/.gitignore | 21 - .../ReactRedux-CSharp/ClientApp/README.md | 2228 --- .../ClientApp/package-lock.json | 13851 ---------------- .../ReactRedux-CSharp/ClientApp/package.json | 58 - .../ClientApp/public/favicon.ico | Bin 32038 -> 0 bytes .../ClientApp/public/index.html | 41 - .../ClientApp/public/manifest.json | 15 - .../ClientApp/src/App.test.tsx | 22 - .../ReactRedux-CSharp/ClientApp/src/App.tsx | 16 - .../ClientApp/src/components/Counter.tsx | 35 - .../ClientApp/src/components/FetchData.tsx | 84 - .../ClientApp/src/components/Home.tsx | 23 - .../ClientApp/src/components/Layout.tsx | 12 - .../ClientApp/src/components/NavMenu.css | 13 - .../ClientApp/src/components/NavMenu.tsx | 42 - .../ClientApp/src/custom.css | 14 - .../ReactRedux-CSharp/ClientApp/src/index.tsx | 27 - .../ClientApp/src/react-app-env.d.ts | 1 - .../ClientApp/src/registerServiceWorker.ts | 105 - .../ClientApp/src/store/Counter.ts | 48 - .../ClientApp/src/store/WeatherForecasts.ts | 91 - .../ClientApp/src/store/configureStore.ts | 29 - .../ClientApp/src/store/index.ts | 22 - .../ReactRedux-CSharp/ClientApp/tsconfig.json | 24 - .../Controllers/WeatherForecastController.cs | 39 - .../ReactRedux-CSharp/Pages/Error.cshtml | 26 - .../ReactRedux-CSharp/Pages/Error.cshtml.cs | 30 - .../Pages/_ViewImports.cshtml | 3 - .../content/ReactRedux-CSharp/Program.cs | 26 - .../Properties/launchSettings.json | 35 - .../content/ReactRedux-CSharp/Startup.cs | 78 - .../ReactRedux-CSharp/WeatherForecast.cs | 15 - .../appsettings.Development.json | 9 - .../ReactRedux-CSharp/appsettings.json | 10 - .../test/ByteOrderMarkTest.cs | 33 +- .../test/Helpers/TemplatePackageInstaller.cs | 2 +- .../test/ProjectTemplates.Tests.csproj | 14 +- 1099 files changed, 1345 insertions(+), 241988 deletions(-) delete mode 100644 src/Components/Analyzers/src/ComponentFacts.cs delete mode 100644 src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs delete mode 100644 src/Components/Analyzers/src/ComponentParameterAnalyzer.cs delete mode 100644 src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs delete mode 100644 src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs delete mode 100644 src/Components/Analyzers/src/ComponentSymbols.cs delete mode 100644 src/Components/Analyzers/src/ComponentsApi.cs delete mode 100644 src/Components/Analyzers/src/DiagnosticDescriptors.cs delete mode 100644 src/Components/Analyzers/src/InternalUsageAnalyzer.cs delete mode 100644 src/Components/Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj delete mode 100644 src/Components/Analyzers/src/Properties/AssemblyInfo.cs delete mode 100644 src/Components/Analyzers/src/Resources.resx delete mode 100644 src/Components/Analyzers/src/build/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.props delete mode 100644 src/Components/Analyzers/test/AnalyzerTestBase.cs delete mode 100644 src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs delete mode 100644 src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesHasWrongTypeTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesMustBeUniqueTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs delete mode 100644 src/Components/Analyzers/test/ComponentsTestDeclarations.cs delete mode 100644 src/Components/Analyzers/test/Helpers/CodeFixVerifier.Helper.cs delete mode 100644 src/Components/Analyzers/test/Helpers/DiagnosticResult.cs delete mode 100644 src/Components/Analyzers/test/Helpers/DiagnosticVerifier.Helper.cs delete mode 100644 src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj delete mode 100644 src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs delete mode 100644 src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs delete mode 100644 src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs delete mode 100644 src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs delete mode 100644 src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.csproj delete mode 100644 src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs delete mode 100644 src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netstandard2.0.cs delete mode 100644 src/Components/Authorization/src/AttributeAuthorizeDataCache.cs delete mode 100644 src/Components/Authorization/src/AuthenticationState.cs delete mode 100644 src/Components/Authorization/src/AuthenticationStateProvider.cs delete mode 100644 src/Components/Authorization/src/AuthorizeDataAdapter.cs delete mode 100644 src/Components/Authorization/src/AuthorizeRouteView.cs delete mode 100644 src/Components/Authorization/src/AuthorizeView.cs delete mode 100644 src/Components/Authorization/src/AuthorizeViewCore.cs delete mode 100644 src/Components/Authorization/src/CascadingAuthenticationState.razor delete mode 100644 src/Components/Authorization/src/IHostEnvironmentAuthenticationStateProvider.cs delete mode 100644 src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj delete mode 100644 src/Components/Authorization/test/AuthorizeRouteViewTest.cs delete mode 100644 src/Components/Authorization/test/AuthorizeViewTest.cs delete mode 100644 src/Components/Authorization/test/CascadingAuthenticationStateTest.cs delete mode 100644 src/Components/Authorization/test/Microsoft.AspNetCore.Components.Authorization.Tests.csproj delete mode 100644 src/Components/Authorization/test/TestAuthenticationStateProvider.cs delete mode 100644 src/Components/Authorization/test/TestAuthorizationPolicyProvider.cs delete mode 100644 src/Components/Authorization/test/TestAuthorizationService.cs delete mode 100644 src/Components/Authorization/test/TestIdentity.cs create mode 100644 src/Components/Blazor.sln create mode 100644 src/Components/Blazor/Blazor.sln delete mode 100644 src/Components/Blazor/Templates/.gitignore delete mode 100644 src/Components/Components.sln delete mode 100644 src/Components/Components/perf/AssemblyInfo.cs delete mode 100644 src/Components/Components/perf/Microsoft.AspNetCore.Components.Performance.csproj delete mode 100644 src/Components/Components/perf/Program.cs delete mode 100644 src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs delete mode 100644 src/Components/Components/perf/readme.md delete mode 100644 src/Components/Components/ref/Directory.Build.props delete mode 100644 src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj delete mode 100644 src/Components/Components/ref/Microsoft.AspNetCore.Components.netcoreapp.cs delete mode 100644 src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs delete mode 100644 src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs delete mode 100644 src/Components/Components/src/BindConverter.cs delete mode 100644 src/Components/Components/src/BindElementAttribute.cs delete mode 100644 src/Components/Components/src/CascadingParameterAttribute.cs delete mode 100644 src/Components/Components/src/CascadingParameterState.cs delete mode 100644 src/Components/Components/src/CascadingValue.cs delete mode 100644 src/Components/Components/src/ChangeDetection.cs delete mode 100644 src/Components/Components/src/ChangeEventArgs.cs delete mode 100644 src/Components/Components/src/CompilerServices/RuntimeHelpers.cs delete mode 100644 src/Components/Components/src/ComponentBase.cs delete mode 100644 src/Components/Components/src/ComponentFactory.cs delete mode 100644 src/Components/Components/src/Dispatcher.cs delete mode 100644 src/Components/Components/src/ElementReference.cs delete mode 100644 src/Components/Components/src/EventCallback.cs delete mode 100644 src/Components/Components/src/EventCallbackFactory.cs delete mode 100644 src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs delete mode 100644 src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs delete mode 100644 src/Components/Components/src/EventCallbackOfT.cs delete mode 100644 src/Components/Components/src/EventCallbackWorkItem.cs delete mode 100644 src/Components/Components/src/EventHandlerAttribute.cs delete mode 100644 src/Components/Components/src/ICascadingValueComponent.cs delete mode 100644 src/Components/Components/src/IComponent.cs delete mode 100644 src/Components/Components/src/IEventCallback.cs delete mode 100644 src/Components/Components/src/IHandleAfterRender.cs delete mode 100644 src/Components/Components/src/IHandleEvent.cs delete mode 100644 src/Components/Components/src/InjectAttribute.cs delete mode 100644 src/Components/Components/src/LayoutAttribute.cs delete mode 100644 src/Components/Components/src/LayoutComponentBase.cs delete mode 100644 src/Components/Components/src/LayoutView.cs delete mode 100644 src/Components/Components/src/LocationChangeException.cs delete mode 100644 src/Components/Components/src/MarkupString.cs delete mode 100644 src/Components/Components/src/Microsoft.AspNetCore.Components.csproj delete mode 100644 src/Components/Components/src/Microsoft.AspNetCore.Components.multitarget.nuspec delete mode 100644 src/Components/Components/src/Microsoft.AspNetCore.Components.netcoreapp.nuspec delete mode 100644 src/Components/Components/src/NavigationException.cs delete mode 100644 src/Components/Components/src/NavigationManager.cs delete mode 100644 src/Components/Components/src/OwningComponentBase.cs delete mode 100644 src/Components/Components/src/ParameterAttribute.cs delete mode 100644 src/Components/Components/src/ParameterValue.cs delete mode 100644 src/Components/Components/src/ParameterView.cs delete mode 100644 src/Components/Components/src/PlatformInfo.cs delete mode 100644 src/Components/Components/src/Properties/AssemblyInfo.cs delete mode 100644 src/Components/Components/src/Reflection/ComponentProperties.cs delete mode 100644 src/Components/Components/src/Reflection/IPropertySetter.cs delete mode 100644 src/Components/Components/src/Reflection/MemberAssignment.cs delete mode 100644 src/Components/Components/src/RenderFragment.cs delete mode 100644 src/Components/Components/src/RenderHandle.cs delete mode 100644 src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs delete mode 100644 src/Components/Components/src/RenderTree/ArrayBuilderSegment.cs delete mode 100644 src/Components/Components/src/RenderTree/ArrayRange.cs delete mode 100644 src/Components/Components/src/RenderTree/EventFieldInfo.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderBatch.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeDiff.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeEdit.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeEditType.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeFrame.cs delete mode 100644 src/Components/Components/src/RenderTree/RenderTreeFrameType.cs delete mode 100644 src/Components/Components/src/RenderTree/Renderer.Log.cs delete mode 100644 src/Components/Components/src/RenderTree/Renderer.cs delete mode 100644 src/Components/Components/src/RenderTree/StackObjectPool.cs delete mode 100644 src/Components/Components/src/Rendering/ComponentState.cs delete mode 100644 src/Components/Components/src/Rendering/KeyedItemInfo.cs delete mode 100644 src/Components/Components/src/Rendering/ParameterViewLifetime.cs delete mode 100644 src/Components/Components/src/Rendering/RenderBatchBuilder.cs delete mode 100644 src/Components/Components/src/Rendering/RenderQueueEntry.cs delete mode 100644 src/Components/Components/src/Rendering/RenderTreeBuilder.cs delete mode 100644 src/Components/Components/src/Rendering/RenderTreeUpdater.cs delete mode 100644 src/Components/Components/src/Rendering/RendererSynchronizationContext.cs delete mode 100644 src/Components/Components/src/Rendering/RendererSynchronizationContextDispatcher.cs delete mode 100644 src/Components/Components/src/RouteAttribute.cs delete mode 100644 src/Components/Components/src/RouteView.cs delete mode 100644 src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs delete mode 100644 src/Components/Components/src/Routing/INavigationInterception.cs delete mode 100644 src/Components/Components/src/Routing/LocationChangedEventArgs.cs delete mode 100644 src/Components/Components/src/Routing/RouteConstraint.cs delete mode 100644 src/Components/Components/src/Routing/RouteContext.cs delete mode 100644 src/Components/Components/src/Routing/RouteData.cs delete mode 100644 src/Components/Components/src/Routing/RouteEntry.cs delete mode 100644 src/Components/Components/src/Routing/RouteTable.cs delete mode 100644 src/Components/Components/src/Routing/RouteTableFactory.cs delete mode 100644 src/Components/Components/src/Routing/RouteTemplate.cs delete mode 100644 src/Components/Components/src/Routing/Router.cs delete mode 100644 src/Components/Components/src/Routing/TemplateParser.cs delete mode 100644 src/Components/Components/src/Routing/TemplateSegment.cs delete mode 100644 src/Components/Components/src/Routing/TypeRouteConstraint.cs delete mode 100644 src/Components/Components/test/BindConverterTest.cs delete mode 100644 src/Components/Components/test/CascadingParameterStateTest.cs delete mode 100644 src/Components/Components/test/CascadingParameterTest.cs delete mode 100644 src/Components/Components/test/ComponentBaseTest.cs delete mode 100644 src/Components/Components/test/ComponentFactoryTest.cs delete mode 100644 src/Components/Components/test/DependencyInjectionTest.cs delete mode 100644 src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs delete mode 100644 src/Components/Components/test/EventCallbackFactoryTest.cs delete mode 100644 src/Components/Components/test/EventCallbackTest.cs delete mode 100644 src/Components/Components/test/LayoutViewTest.cs delete mode 100644 src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj delete mode 100644 src/Components/Components/test/NavigationManagerTest.cs delete mode 100644 src/Components/Components/test/OwningComponentBaseTest.cs delete mode 100644 src/Components/Components/test/ParameterViewTest.Assignment.cs delete mode 100644 src/Components/Components/test/ParameterViewTest.cs delete mode 100644 src/Components/Components/test/RenderTreeDiffBuilderTest.cs delete mode 100644 src/Components/Components/test/RenderTreeUpdaterTest.cs delete mode 100644 src/Components/Components/test/RendererTest.cs delete mode 100644 src/Components/Components/test/Rendering/ArrayBuilderSegmentTest.cs delete mode 100644 src/Components/Components/test/Rendering/ArrayBuilderTest.cs delete mode 100644 src/Components/Components/test/Rendering/RenderTreeBuilderTest.cs delete mode 100644 src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs delete mode 100644 src/Components/Components/test/Rendering/TestArrayPool.cs delete mode 100644 src/Components/Components/test/RouteViewTest.cs delete mode 100644 src/Components/Components/test/Routing/RouteConstraintTest.cs delete mode 100644 src/Components/Components/test/Routing/RouteTableFactoryTests.cs delete mode 100644 src/Components/Components/test/Routing/TemplateParserTests.cs delete mode 100644 src/Components/Components/test/StackObjectPoolTest.cs delete mode 100644 src/Components/ComponentsNoDeps.slnf delete mode 100644 src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.csproj delete mode 100644 src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netcoreapp.cs delete mode 100644 src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netstandard2.0.cs delete mode 100644 src/Components/Forms/src/DataAnnotationsValidator.cs delete mode 100644 src/Components/Forms/src/EditContext.cs delete mode 100644 src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs delete mode 100644 src/Components/Forms/src/FieldChangedEventArgs.cs delete mode 100644 src/Components/Forms/src/FieldIdentifier.cs delete mode 100644 src/Components/Forms/src/FieldState.cs delete mode 100644 src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj delete mode 100644 src/Components/Forms/src/ValidationMessageStore.cs delete mode 100644 src/Components/Forms/src/ValidationRequestedEventArgs.cs delete mode 100644 src/Components/Forms/src/ValidationStateChangedEventArgs.cs delete mode 100644 src/Components/Forms/test/EditContextDataAnnotationsExtensionsTest.cs delete mode 100644 src/Components/Forms/test/EditContextTest.cs delete mode 100644 src/Components/Forms/test/FieldIdentifierTest.cs delete mode 100644 src/Components/Forms/test/Microsoft.AspNetCore.Components.Forms.Tests.csproj delete mode 100644 src/Components/Forms/test/ValidationMessageStoreTest.cs delete mode 100644 src/Components/Ignitor/src/BlazorClient.cs delete mode 100644 src/Components/Ignitor/src/CancellableOperation.cs delete mode 100644 src/Components/Ignitor/src/CapturedAttachComponentCall.cs delete mode 100644 src/Components/Ignitor/src/CapturedJSInteropCall.cs delete mode 100644 src/Components/Ignitor/src/CapturedRenderBatch.cs delete mode 100644 src/Components/Ignitor/src/CommentNode.cs delete mode 100644 src/Components/Ignitor/src/ComponentNode.cs delete mode 100644 src/Components/Ignitor/src/ComponentState.cs delete mode 100644 src/Components/Ignitor/src/ContainerNode.cs delete mode 100644 src/Components/Ignitor/src/ElementHive.cs delete mode 100644 src/Components/Ignitor/src/ElementNode.cs delete mode 100644 src/Components/Ignitor/src/ElementReference.cs delete mode 100644 src/Components/Ignitor/src/Error.cs delete mode 100644 src/Components/Ignitor/src/IComponent.cs delete mode 100644 src/Components/Ignitor/src/Ignitor.csproj delete mode 100644 src/Components/Ignitor/src/IgnitorMessagePackHubProtocol.cs delete mode 100644 src/Components/Ignitor/src/MarkupNode.cs delete mode 100644 src/Components/Ignitor/src/Node.cs delete mode 100644 src/Components/Ignitor/src/NodeSerializer.cs delete mode 100644 src/Components/Ignitor/src/Operations.cs delete mode 100644 src/Components/Ignitor/src/Properties/AssemblyInfo.cs delete mode 100644 src/Components/Ignitor/src/RenderBatchReader.cs delete mode 100644 src/Components/Ignitor/src/TextNode.cs delete mode 100644 src/Components/Ignitor/test/Ignitor.Test.csproj delete mode 100644 src/Components/Ignitor/test/RenderBatchReaderTest.cs delete mode 100644 src/Components/Samples/BlazorServerApp/App.razor delete mode 100644 src/Components/Samples/BlazorServerApp/BlazorServerApp.csproj delete mode 100644 src/Components/Samples/BlazorServerApp/Data/WeatherForecast.cs delete mode 100644 src/Components/Samples/BlazorServerApp/Data/WeatherForecastService.cs delete mode 100644 src/Components/Samples/BlazorServerApp/Pages/Counter.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Pages/Error.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Pages/FetchData.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Pages/Index.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Pages/_Host.cshtml delete mode 100644 src/Components/Samples/BlazorServerApp/Program.cs delete mode 100644 src/Components/Samples/BlazorServerApp/Shared/MainLayout.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Shared/NavMenu.razor delete mode 100644 src/Components/Samples/BlazorServerApp/Startup.cs delete mode 100644 src/Components/Samples/BlazorServerApp/_Imports.razor delete mode 100644 src/Components/Samples/BlazorServerApp/appsettings.Development.json delete mode 100644 src/Components/Samples/BlazorServerApp/appsettings.json delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/bootstrap/bootstrap.min.css delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/bootstrap/bootstrap.min.css.map delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/FONT-LICENSE delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/ICON-LICENSE delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/README.md delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/fonts/open-iconic.eot delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/fonts/open-iconic.otf delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/fonts/open-iconic.svg delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/open-iconic/font/fonts/open-iconic.woff delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/css/site.css delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/favicon.ico delete mode 100644 src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.csproj delete mode 100644 src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.netcoreapp.cs delete mode 100644 src/Components/Server/src/BlazorPack/ArrayBufferWriter.cs delete mode 100644 src/Components/Server/src/BlazorPack/BlazorPackHubProtocol.cs delete mode 100644 src/Components/Server/src/BlazorPack/NonDefaultHubProtocolAttribute.cs delete mode 100644 src/Components/Server/src/BlazorPack/Requires.cs delete mode 100644 src/Components/Server/src/BlazorPack/SequenceOfT.cs delete mode 100644 src/Components/Server/src/Builder/ComponentEndpointConventionBuilder.cs delete mode 100644 src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs delete mode 100644 src/Components/Server/src/CircuitDisconnectMiddleware.cs delete mode 100644 src/Components/Server/src/CircuitOptions.cs delete mode 100644 src/Components/Server/src/Circuits/ArrayBuilderMemoryStream.cs delete mode 100644 src/Components/Server/src/Circuits/Circuit.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitClientProxy.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitFactory.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitHandle.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitHandler.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitHost.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitId.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitIdFactory.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs delete mode 100644 src/Components/Server/src/Circuits/CircuitRegistry.cs delete mode 100644 src/Components/Server/src/Circuits/ComponentDescriptor.cs delete mode 100644 src/Components/Server/src/Circuits/ComponentParameterDeserializer.cs delete mode 100644 src/Components/Server/src/Circuits/ComponentParametersTypeCache.cs delete mode 100644 src/Components/Server/src/Circuits/DefaultCircuitAccessor.cs delete mode 100644 src/Components/Server/src/Circuits/ICircuitAccessor.cs delete mode 100644 src/Components/Server/src/Circuits/RemoteJSRuntime.cs delete mode 100644 src/Components/Server/src/Circuits/RemoteNavigationInterception.cs delete mode 100644 src/Components/Server/src/Circuits/RemoteNavigationManager.cs delete mode 100644 src/Components/Server/src/Circuits/RemoteRenderer.cs delete mode 100644 src/Components/Server/src/Circuits/RenderBatchWriter.cs delete mode 100644 src/Components/Server/src/Circuits/RevalidatingServerAuthenticationStateProvider.cs delete mode 100644 src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs delete mode 100644 src/Components/Server/src/Circuits/ServerComponentDeserializer.cs delete mode 100644 src/Components/Server/src/Circuits/ServerComponentTypeCache.cs delete mode 100644 src/Components/Server/src/ComponentHub.cs delete mode 100644 src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs delete mode 100644 src/Components/Server/src/DependencyInjection/ConfigureStaticFilesOptions.cs delete mode 100644 src/Components/Server/src/DependencyInjection/IServerSideBlazorBuilder.cs delete mode 100644 src/Components/Server/src/DependencyInjection/ServerSideBlazorBuilderExtensions.cs delete mode 100644 src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj delete mode 100644 src/Components/Server/src/Properties/AssemblyInfo.cs delete mode 100644 src/Components/Server/test/BlazorPack/BlazorPackHubProtocolTest.cs delete mode 100644 src/Components/Server/test/CircuitDisconnectMiddlewareTest.cs delete mode 100644 src/Components/Server/test/Circuits/CircuitClientProxyTest.cs delete mode 100644 src/Components/Server/test/Circuits/CircuitHostTest.cs delete mode 100644 src/Components/Server/test/Circuits/CircuitIdFactoryTest.cs delete mode 100644 src/Components/Server/test/Circuits/CircuitRegistryTest.cs delete mode 100644 src/Components/Server/test/Circuits/RemoteRendererTest.cs delete mode 100644 src/Components/Server/test/Circuits/RenderBatchWriterTest.cs delete mode 100644 src/Components/Server/test/Circuits/RevalidatingServerAuthenticationStateProvider.cs delete mode 100644 src/Components/Server/test/Circuits/ServerAuthenticationStateProviderTest.cs delete mode 100644 src/Components/Server/test/Circuits/ServerComponentDeserializerTest.cs delete mode 100644 src/Components/Server/test/Circuits/TestCircuitHost.cs delete mode 100644 src/Components/Server/test/Circuits/TestCircuitIdFactory.cs delete mode 100644 src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs delete mode 100644 src/Components/Server/test/DependencyInjection/ComponentServiceCollectionExtensionsTest.cs delete mode 100644 src/Components/Server/test/ElementReferenceJsonConverterTest.cs delete mode 100644 src/Components/Server/test/Microsoft.AspNetCore.Components.Server.Tests.csproj delete mode 100644 src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.csproj delete mode 100644 src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netcoreapp.cs delete mode 100644 src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs delete mode 100644 src/Components/Web/src/BindInputElementAttribute.cs delete mode 100644 src/Components/Web/src/Forms/EditContextFieldClassExtensions.cs delete mode 100644 src/Components/Web/src/Forms/EditForm.cs delete mode 100644 src/Components/Web/src/Forms/InputBase.cs delete mode 100644 src/Components/Web/src/Forms/InputCheckbox.cs delete mode 100644 src/Components/Web/src/Forms/InputDate.cs delete mode 100644 src/Components/Web/src/Forms/InputNumber.cs delete mode 100644 src/Components/Web/src/Forms/InputSelect.cs delete mode 100644 src/Components/Web/src/Forms/InputText.cs delete mode 100644 src/Components/Web/src/Forms/InputTextArea.cs delete mode 100644 src/Components/Web/src/Forms/ValidationMessage.cs delete mode 100644 src/Components/Web/src/Forms/ValidationSummary.cs delete mode 100644 src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj delete mode 100644 src/Components/Web/src/Properties/AssemblyInfo.cs delete mode 100644 src/Components/Web/src/Routing/NavLink.cs delete mode 100644 src/Components/Web/src/Routing/NavLinkMatch.cs delete mode 100644 src/Components/Web/src/Web/BindAttributes.cs delete mode 100644 src/Components/Web/src/Web/ClipboardEventArgs.cs delete mode 100644 src/Components/Web/src/Web/DataTransfer.cs delete mode 100644 src/Components/Web/src/Web/DataTransferItem.cs delete mode 100644 src/Components/Web/src/Web/DragEventArgs.cs delete mode 100644 src/Components/Web/src/Web/ErrorEventArgs.cs delete mode 100644 src/Components/Web/src/Web/EventHandlers.cs delete mode 100644 src/Components/Web/src/Web/FocusEventArgs.cs delete mode 100644 src/Components/Web/src/Web/KeyboardEventArgs.cs delete mode 100644 src/Components/Web/src/Web/MouseEventArgs.cs delete mode 100644 src/Components/Web/src/Web/PointerEventArgs.cs delete mode 100644 src/Components/Web/src/Web/ProgressEventArgs.cs delete mode 100644 src/Components/Web/src/Web/TouchEventArgs.cs delete mode 100644 src/Components/Web/src/Web/TouchPoint.cs delete mode 100644 src/Components/Web/src/Web/WebEventCallbackFactoryEventArgsExtensions.cs delete mode 100644 src/Components/Web/src/Web/WebRenderTreeBuilderExtensions.cs delete mode 100644 src/Components/Web/src/Web/WheelEventArgs.cs delete mode 100644 src/Components/Web/src/WebEventDescriptor.cs delete mode 100644 src/Components/Web/test/Forms/InputBaseTest.cs delete mode 100644 src/Components/Web/test/Microsoft.AspNetCore.Components.Web.Tests.csproj delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/Microsoft.DotNet.Web.Client.ItemTemplates.csproj delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Less/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Less/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Less/styleSheet1.less delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Scss/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Scss/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/Scss/styleSheet1.scss delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/TypeScript/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/TypeScript/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Client.ItemTemplates/content/TypeScript/file1.ts delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/Microsoft.DotNet.Web.ItemTemplates.csproj delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/Protobuf/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/Protobuf/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/Protobuf/protobuf.proto delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/Component1.razor delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorPage/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorPage/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorPage/Index.cshtml delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/RazorPage/Index.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewImports/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewImports/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewImports/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewStart/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewStart/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ItemTemplates/content/ViewStart/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/.gitignore delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/BlazorServerWeb-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/EmptyWeb-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/EmptyWeb-FSharp.fsproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/GrpcService-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/RazorPagesWeb-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-FSharp.fsproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/WebApi-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/WebApi-FSharp.fsproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/Worker-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/vs-2017.3/icon.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/App.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/Identity/Pages/Account/LogOut.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/Identity/Pages/Shared/_LoginPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/Identity/RevalidatingIdentityAuthenticationStateProvider.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/WeatherForecast.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Data/WeatherForecastService.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/Counter.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/Error.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/FetchData.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/Index.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Host.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/LoginDisplay.IndividualB2CAuth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/LoginDisplay.IndividualLocalAuth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/LoginDisplay.OrganizationalAuth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/LoginDisplay.WindowsAuth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/MainLayout.Auth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/MainLayout.NoAuth.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/NavMenu.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/_Imports.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/app.db delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/bootstrap/bootstrap.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/bootstrap/bootstrap.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/FONT-LICENSE delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/ICON-LICENSE delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/README.md delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/fonts/open-iconic.eot delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/fonts/open-iconic.otf delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/fonts/open-iconic.svg delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/open-iconic/font/fonts/open-iconic.woff delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/css/site.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Directory.Build.props delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Directory.Build.targets delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/vs-2017.3/Empty.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/vs-2017.3/Empty.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Program.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Startup.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/vs-2017.3/gRPC.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/Protos/greet.proto delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/Services/GreeterService.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3/RazorClassLibrary.ico delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Areas/MyFeature/Pages/Page1.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Areas/MyFeature/Pages/Page1.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/_Imports.razor delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/vs-2017.3/WebApplication.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Areas/Identity/Pages/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Error.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Index.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Index.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Privacy.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Privacy.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_Layout.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.Identity.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.OrgAuth.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_ValidationScriptsPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/app.db delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/css/site.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/js/site.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/LICENSE delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation/LICENSE.md delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation/dist/additional-methods.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation/dist/additional-methods.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery/dist/jquery.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery/dist/jquery.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/lib/jquery/dist/jquery.min.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/vs-2017.3/WebApplication.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Areas/Identity/Pages/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Controllers/HomeController.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Models/ErrorViewModel.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Home/Index.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Home/Privacy.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_Layout.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.Identity.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.OrgAuth.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_ValidationScriptsPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Views/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/app.db delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/css/site.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/js/site.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/LICENSE delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation/LICENSE.md delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation/dist/additional-methods.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation/dist/additional-methods.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery/dist/jquery.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery/dist/jquery.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/lib/jquery/dist/jquery.min.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Controllers/HomeController.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Models/ErrorViewModel.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Program.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/Home/Index.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/Home/Privacy.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/Shared/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/Shared/_Layout.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/Shared/_ValidationScriptsPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Views/_ViewStart.cshtml delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/css/site.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/js/site.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/LICENSE delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation/LICENSE.md delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation/dist/additional-methods.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation/dist/additional-methods.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery/LICENSE.txt delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery/dist/jquery.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery/dist/jquery.min.js delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/lib/jquery/dist/jquery.min.map delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/vs-2017.3/WebAPI.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Controllers/WeatherForecastController.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/WeatherForecast.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/vs-2017.3/WebAPI.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Controllers/WeatherForecastController.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Program.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/WeatherForecast.fs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/vs-2017.3/Worker.png delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/Worker.cs delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/Worker-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/React-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/ReactRedux-CSharp.csproj.in delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/icon.png delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/.editorconfig delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/README.md delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/angular.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/browserslist delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/e2e/protractor.conf.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/e2e/src/app.e2e-spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/e2e/src/app.po.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/e2e/tsconfig.e2e.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package-lock.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/package.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.constants.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.module.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/app.server.module.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/counter/counter.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/counter/counter.component.spec.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/counter/counter.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/home/home.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/home/home.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/assets/.gitkeep delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/environments/environment.prod.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/environments/environment.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/index.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/karma.conf.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/main.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/polyfills.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/styles.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/test.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/tsconfig.app.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/tsconfig.server.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/tsconfig.spec.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/tslint.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/tsconfig.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/tslint.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Controllers/OidcConfigurationController.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Controllers/WeatherForecastController.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Models/ApplicationUser.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Pages/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Pages/Error.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Pages/Shared/_LoginPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Pages/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/WeatherForecast.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/app.db delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/wwwroot/favicon.ico delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Directory.Build.props delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Directory.Build.targets delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/icon.png delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/README.md delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/package-lock.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/package.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/public/favicon.ico delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/public/index.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/public/manifest.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/App.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/App.test.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/Counter.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/FetchData.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/Home.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/Layout.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/NavMenu.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/NavMenu.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/ApiAuthorizationConstants.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/ApiAuthorizationRoutes.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/AuthorizeRoute.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/AuthorizeService.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/Login.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/LoginMenu.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/components/api-authorization/Logout.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/custom.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/index.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/registerServiceWorker.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/ClientApp/src/setupTests.js delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Controllers/OidcConfigurationController.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Controllers/WeatherForecastController.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/ApplicationDbContext.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Models/ApplicationUser.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Pages/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Pages/Error.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Pages/Shared/_LoginPartial.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Pages/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/WeatherForecast.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/app.db delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/appsettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/cs-CZ/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/de-DE/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/dotnetcli.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/en/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/es-ES/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/fr-FR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/icon.png delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/it-IT/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/ja-JP/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/ko-KR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/pl-PL/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/pt-BR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/ru-RU/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/template.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/tr-TR/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/vs-2017.3.host.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/zh-CN/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/.template.config/zh-TW/strings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/.eslintrc.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/.gitignore delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/README.md delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/package-lock.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/package.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/public/favicon.ico delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/public/index.html delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/public/manifest.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/App.test.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/App.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/Counter.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/FetchData.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/Home.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/Layout.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/NavMenu.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/components/NavMenu.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/custom.css delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/index.tsx delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/react-app-env.d.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/registerServiceWorker.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/store/Counter.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/store/WeatherForecasts.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/store/configureStore.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/src/store/index.ts delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/ClientApp/tsconfig.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Controllers/WeatherForecastController.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Pages/Error.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Pages/Error.cshtml.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Pages/_ViewImports.cshtml delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Program.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Properties/launchSettings.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/WeatherForecast.cs delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/appsettings.Development.json delete mode 100644 src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/appsettings.json diff --git a/NuGet.config b/NuGet.config index d62ece6b60ae..83bc90a901f0 100644 --- a/NuGet.config +++ b/NuGet.config @@ -6,6 +6,7 @@ + diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props index b5c81965354d..05508591091c 100644 --- a/eng/Baseline.Designer.props +++ b/eng/Baseline.Designer.props @@ -2,106 +2,106 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.1.0 + 3.1.1 - 3.0.0 + 3.0.2 - 3.0.0 + 3.0.2 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - - - + + + - + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 @@ -109,39 +109,39 @@ - 3.1.0 + 3.1.1 - - - + + + - - - + + + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + @@ -186,273 +186,273 @@ - 3.1.0 + 3.1.1 - - - + + + - - - + + + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - - + + - - + + - 3.1.0 + 3.1.1 - + - + - 3.1.0 + 3.1.1 - - - - + + + + - - - - + + + + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - + - + - + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - + - + - 3.1.0 + 3.1.1 - - - - - - + + + + + + - - - - - - + + + + + + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - - + + - - + + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - - - + + + - - - + + + - 3.1.0 + 3.1.1 - + - + - 3.1.0 + 3.1.1 - + - + - 3.1.0 + 3.1.1 - - + + - - + + - 3.1.0 + 3.1.1 - - - - + + + + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 @@ -460,236 +460,238 @@ - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - - - + + + - 3.1.0 + 3.1.1 - - - + + + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - + - - + + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - - + + - - + + - - - - + + + + - 3.1.0 + 3.1.1 - - + + - - + + - 3.1.0 + 3.1.1 - + - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - - - - + + + + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - + - 3.1.0 + 3.1.1 - - + + - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - 3.1.0 + 3.1.1 - - - + + + - 3.1.0 + 3.1.1 - - - + + + - - - + + + - 3.1.0 + 3.1.1 - - + + + - - + + + \ No newline at end of file diff --git a/eng/Baseline.xml b/eng/Baseline.xml index 9a5276d72971..d479dfe6ce0a 100644 --- a/eng/Baseline.xml +++ b/eng/Baseline.xml @@ -4,86 +4,86 @@ This file contains a list of all the packages and their versions which were rele Update this list when preparing for a new patch. --> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 2e11857b1b9a..6ec858033d60 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -147,6 +147,16 @@ and are generated based on the last package release. + + + + + + + + + + diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index 350c026a7d67..a14d2cf64269 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -5,143 +5,12 @@ --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/eng/Versions.props b/eng/Versions.props index acef5287d107..664c95dbeb55 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -8,8 +8,8 @@ 3 1 - 0 - 3 + 2 + 0 @@ -19,21 +19,21 @@ false preview$(PreReleasePreviewNumber) Preview $(PreReleasePreviewNumber) + + 4 + preview$(BlazorClientPreReleasePreviewNumber) $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + + 3.1.0 false - - true - - true + + true $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion) $(VersionPrefix) - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0 + $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).2 0.3.$(AspNetCorePatchVersion) $([MSBuild]::Add(10, $(AspNetCoreMajorVersion))) @@ -62,14 +62,15 @@ --> - 1.0.0-beta.19577.5 + 1.0.0-beta.19607.3 - 3.4.0-beta4-19569-03 + 3.4.1-beta4-19614-01 - 3.1.1-servicing.19575.1 - 3.1.1-servicing.19576.9 + 3.1.2 + 3.1.2-servicing.20067.4 3.1.0 - 3.1.1-servicing.19575.1 + 3.1.2 + 3.1.2 2.1.0 1.1.0 @@ -91,7 +92,7 @@ 4.7.0 4.7.0 4.7.0 - 4.7.0 + 4.7.1 4.7.0 4.7.0 @@ -99,80 +100,80 @@ 3.2.0-preview1.20067.1 - 3.1.0-rtm.19575.5 - 3.1.0-rtm.19575.5 - 3.1.0-rtm.19575.5 - 3.1.0-rtm.19575.5 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0 - 3.1.0-rtm.19575.5 - 3.1.0-rtm.19575.5 - 3.1.0 + 3.1.2-servicing.20067.6 + 3.1.2-servicing.20067.6 + 3.1.2-servicing.20067.6 + 3.1.2-servicing.20067.6 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2 + 3.1.2-servicing.20067.6 + 3.1.2-servicing.20067.6 + 3.1.2 3.1.0-rtm.19565.4 - 3.1.0 - 3.1.0-preview4.19575.5 + 3.1.2 + 3.1.2-preview4.20067.6 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 - 3.1.0 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 - 3.1.0-rtm.19573.1 + 3.1.2 + 3.1.2 + 3.1.2 + 3.1.2 $(MicrosoftNETCoreAppRuntimewinx64PackageVersion) + 3.1.2 @@ -264,10 +266,19 @@ $(XunitVersion) $(XunitVersion) 1.0.19249.1 + + + 3.1.2-servicing.20068.1 + 3.1.2 + $(MicrosoftAspNetCoreComponentsPackageVersion) + $(MicrosoftAspNetCoreComponentsPackageVersion) + $(MicrosoftAspNetCoreComponentsPackageVersion) + $(MicrosoftAspNetCoreComponentsPackageVersion) https://dotnetcli.blob.core.windows.net/dotnet/ + https://dotnetclimsrc.blob.core.windows.net/dotnet/ - + \ No newline at end of file diff --git a/global.json b/global.json index 88df91565f15..324a0158be07 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "3.1.100" + "version": "3.1.102-servicing-014873" }, "tools": { - "dotnet": "3.1.100", + "dotnet": "3.1.102-servicing-014873", "runtimes": { "dotnet/x64": [ "$(MicrosoftNETCoreAppInternalPackageVersion)" diff --git a/src/Components/Analyzers/src/ComponentFacts.cs b/src/Components/Analyzers/src/ComponentFacts.cs deleted file mode 100644 index 75403ce282a5..000000000000 --- a/src/Components/Analyzers/src/ComponentFacts.cs +++ /dev/null @@ -1,111 +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 Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - internal static class ComponentFacts - { - public static bool IsAnyParameter(ComponentSymbols symbols, IPropertySymbol property) - { - if (symbols == null) - { - throw new ArgumentNullException(nameof(symbols)); - } - - if (property == null) - { - throw new ArgumentNullException(nameof(property)); - } - - return property.GetAttributes().Any(a => - { - return a.AttributeClass == symbols.ParameterAttribute || a.AttributeClass == symbols.CascadingParameterAttribute; - }); - } - - public static bool IsParameter(ComponentSymbols symbols, IPropertySymbol property) - { - if (symbols == null) - { - throw new ArgumentNullException(nameof(symbols)); - } - - if (property == null) - { - throw new ArgumentNullException(nameof(property)); - } - - return property.GetAttributes().Any(a => a.AttributeClass == symbols.ParameterAttribute); - } - - public static bool IsParameterWithCaptureUnmatchedValues(ComponentSymbols symbols, IPropertySymbol property) - { - if (symbols == null) - { - throw new ArgumentNullException(nameof(symbols)); - } - - if (property == null) - { - throw new ArgumentNullException(nameof(property)); - } - - var attribute = property.GetAttributes().FirstOrDefault(a => a.AttributeClass == symbols.ParameterAttribute); - if (attribute == null) - { - return false; - } - - foreach (var kvp in attribute.NamedArguments) - { - if (string.Equals(kvp.Key, ComponentsApi.ParameterAttribute.CaptureUnmatchedValues, StringComparison.Ordinal)) - { - return kvp.Value.Value as bool? ?? false; - } - } - - return false; - } - - public static bool IsCascadingParameter(ComponentSymbols symbols, IPropertySymbol property) - { - if (symbols == null) - { - throw new ArgumentNullException(nameof(symbols)); - } - - if (property == null) - { - throw new ArgumentNullException(nameof(property)); - } - - return property.GetAttributes().Any(a => a.AttributeClass == symbols.CascadingParameterAttribute); - } - - public static bool IsComponent(ComponentSymbols symbols, Compilation compilation, INamedTypeSymbol type) - { - if (symbols is null) - { - throw new ArgumentNullException(nameof(symbols)); - } - - if (type is null) - { - throw new ArgumentNullException(nameof(type)); - } - - var conversion = compilation.ClassifyConversion(symbols.IComponentType, type); - if (!conversion.Exists || !conversion.IsExplicit) - { - return false; - } - - return true; - } - } -} diff --git a/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs b/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs deleted file mode 100644 index 8f6272c32639..000000000000 --- a/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs +++ /dev/null @@ -1,43 +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.Collections.Immutable; -using Microsoft.AspNetCore.Components.Analyzers; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Microsoft.Extensions.Internal -{ - /// - /// This API supports infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public class ComponentInternalUsageDiagnosticAnalyzer : DiagnosticAnalyzer - { - private readonly InternalUsageAnalyzer _inner; - - public ComponentInternalUsageDiagnosticAnalyzer() - { - // We don't have in *internal* attribute in Blazor. - _inner = new InternalUsageAnalyzer(IsInInternalNamespace, hasInternalAttribute: null, DiagnosticDescriptors.DoNotUseRenderTreeTypes); - } - - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptors.DoNotUseRenderTreeTypes); - - public override void Initialize(AnalysisContext context) - { - _inner.Register(context); - } - - private static bool IsInInternalNamespace(ISymbol symbol) - { - if (symbol?.ContainingNamespace?.ToDisplayString() is string ns) - { - return string.Equals(ns, "Microsoft.AspNetCore.Components.RenderTree"); - } - - return false; - } - } -} diff --git a/src/Components/Analyzers/src/ComponentParameterAnalyzer.cs b/src/Components/Analyzers/src/ComponentParameterAnalyzer.cs deleted file mode 100644 index c6d8670dcb2b..000000000000 --- a/src/Components/Analyzers/src/ComponentParameterAnalyzer.cs +++ /dev/null @@ -1,125 +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.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public class ComponentParameterAnalyzer : DiagnosticAnalyzer - { - public ComponentParameterAnalyzer() - { - SupportedDiagnostics = ImmutableArray.Create(new[] - { - DiagnosticDescriptors.ComponentParametersShouldBePublic, - DiagnosticDescriptors.ComponentParameterSettersShouldBePublic, - DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesMustBeUnique, - DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesHasWrongType, - }); - } - - public override ImmutableArray SupportedDiagnostics { get; } - - public override void Initialize(AnalysisContext context) - { - context.RegisterCompilationStartAction(context => - { - if (!ComponentSymbols.TryCreate(context.Compilation, out var symbols)) - { - // Types we need are not defined. - return; - } - - // This operates per-type because one of the validations we need has to look for duplicates - // defined on the same type. - context.RegisterSymbolStartAction(context => - { - var properties = new List(); - - var type = (INamedTypeSymbol)context.Symbol; - foreach (var member in type.GetMembers()) - { - if (member is IPropertySymbol property && ComponentFacts.IsParameter(symbols, property)) - { - // Annotated with [Parameter]. We ignore [CascadingParameter]'s because they don't interact with tooling and don't currently have any analyzer restrictions. - properties.Add(property); - } - } - - if (properties.Count == 0) - { - return; - } - - context.RegisterSymbolEndAction(context => - { - var captureUnmatchedValuesParameters = new List(); - - // Per-property validations - foreach (var property in properties) - { - var propertyLocation = property.Locations.FirstOrDefault(); - if (propertyLocation == null) - { - continue; - } - - if (property.DeclaredAccessibility != Accessibility.Public) - { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.ComponentParametersShouldBePublic, - propertyLocation, - property.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); - } - else if (property.SetMethod?.DeclaredAccessibility != Accessibility.Public) - { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.ComponentParameterSettersShouldBePublic, - propertyLocation, - property.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); - } - - if (ComponentFacts.IsParameterWithCaptureUnmatchedValues(symbols, property)) - { - captureUnmatchedValuesParameters.Add(property); - - // Check the type, we need to be able to assign a Dictionary - var conversion = context.Compilation.ClassifyConversion(symbols.ParameterCaptureUnmatchedValuesRuntimeType, property.Type); - if (!conversion.Exists || conversion.IsExplicit) - { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesHasWrongType, - propertyLocation, - property.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), - property.Type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), - symbols.ParameterCaptureUnmatchedValuesRuntimeType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); - } - } - } - - // Check if the type defines multiple CaptureUnmatchedValues parameters. Doing this outside the loop means we place the - // errors on the type. - if (captureUnmatchedValuesParameters.Count > 1) - { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesMustBeUnique, - context.Symbol.Locations[0], - type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), - Environment.NewLine, - string.Join( - Environment.NewLine, - captureUnmatchedValuesParameters.Select(p => p.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)).OrderBy(n => n)))); - } - }); - }, SymbolKind.NamedType); - }); - } - } -} diff --git a/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs b/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs deleted file mode 100644 index 8df3167b8311..000000000000 --- a/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs +++ /dev/null @@ -1,114 +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.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Operations; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public class ComponentParameterUsageAnalyzer : DiagnosticAnalyzer - { - public ComponentParameterUsageAnalyzer() - { - SupportedDiagnostics = ImmutableArray.Create(new[] - { - DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent, - }); - } - - public override ImmutableArray SupportedDiagnostics { get; } - - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); - context.RegisterCompilationStartAction(context => - { - if (!ComponentSymbols.TryCreate(context.Compilation, out var symbols)) - { - // Types we need are not defined. - return; - } - - context.RegisterOperationBlockStartAction(startBlockContext => - { - startBlockContext.RegisterOperationAction(context => - { - IOperation leftHandSide; - - if (context.Operation is IAssignmentOperation assignmentOperation) - { - leftHandSide = assignmentOperation.Target; - } - else - { - var incrementOrDecrementOperation = (IIncrementOrDecrementOperation)context.Operation; - leftHandSide = incrementOrDecrementOperation.Target; - } - - if (leftHandSide == null) - { - // Malformed assignment, no left hand side. - return; - } - - if (leftHandSide.Kind != OperationKind.PropertyReference) - { - // We don't want to capture situations where a user does - // MyOtherProperty = aComponent.SomeParameter - return; - } - - var propertyReference = (IPropertyReferenceOperation)leftHandSide; - var componentProperty = (IPropertySymbol)propertyReference.Member; - - if (!ComponentFacts.IsParameter(symbols, componentProperty)) - { - // This is not a property reference that we care about, it is not decorated with [Parameter]. - return; - } - - var propertyContainingType = componentProperty.ContainingType; - if (!ComponentFacts.IsComponent(symbols, context.Compilation, propertyContainingType)) - { - // Someone referenced a property as [Parameter] inside something that is not a component. - return; - } - - var assignmentContainingType = startBlockContext.OwningSymbol?.ContainingType; - if (assignmentContainingType == null) - { - // Assignment location has no containing type. Most likely we're operating on malformed code, don't try and validate. - return; - } - - var conversion = context.Compilation.ClassifyConversion(propertyContainingType, assignmentContainingType); - if (conversion.Exists && conversion.IsIdentity) - { - // The assignment is taking place inside of the declaring component. - return; - } - - if (conversion.Exists && conversion.IsExplicit) - { - // The assignment is taking place within the components type hierarchy. This means the user is setting this in a supported - // scenario. - return; - } - - // At this point the user is referencing a component parameter outside of its declaring class. - - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent, - propertyReference.Syntax.GetLocation(), - propertyReference.Member.Name)); - }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.CoalesceAssignment, OperationKind.Increment, OperationKind.Decrement); - }); - }); - } - } -} diff --git a/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs b/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs deleted file mode 100644 index 173633f0e9fd..000000000000 --- a/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs +++ /dev/null @@ -1,88 +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.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ComponentParametersShouldBePublicCodeFixProvider)), Shared] - public class ComponentParametersShouldBePublicCodeFixProvider : CodeFixProvider - { - private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.ComponentParametersShouldBePublic_FixTitle), Resources.ResourceManager, typeof(Resources)); - - public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(DiagnosticDescriptors.ComponentParametersShouldBePublic.Id); - - public sealed override FixAllProvider GetFixAllProvider() - { - // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers - return WellKnownFixAllProviders.BatchFixer; - } - - public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); - var diagnostic = context.Diagnostics.First(); - var diagnosticSpan = diagnostic.Location.SourceSpan; - - // Find the type declaration identified by the diagnostic. - var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - - // Register a code action that will invoke the fix. - var title = Title.ToString(); - context.RegisterCodeFix( - CodeAction.Create( - title: title, - createChangedDocument: c => GetTransformedDocumentAsync(context.Document, root, declaration), - equivalenceKey: title), - diagnostic); - } - - private Task GetTransformedDocumentAsync( - Document document, - SyntaxNode root, - PropertyDeclarationSyntax declarationNode) - { - var updatedDeclarationNode = HandlePropertyDeclaration(declarationNode); - var newSyntaxRoot = root.ReplaceNode(declarationNode, updatedDeclarationNode); - return Task.FromResult(document.WithSyntaxRoot(newSyntaxRoot)); - } - - private SyntaxNode HandlePropertyDeclaration(PropertyDeclarationSyntax node) - { - TypeSyntax type = node.Type; - if (type == null || type.IsMissing) - { - return null; - } - - var newModifiers = node.Modifiers; - for (var i = 0; i < node.Modifiers.Count; i++) - { - var modifier = node.Modifiers[i]; - if (modifier.IsKind(SyntaxKind.PrivateKeyword) || - modifier.IsKind(SyntaxKind.ProtectedKeyword) || - modifier.IsKind(SyntaxKind.InternalKeyword) || - - // We also remove public in case the user has written something totally backwards such as private public protected Foo - modifier.IsKind(SyntaxKind.PublicKeyword)) - { - newModifiers = newModifiers.Remove(modifier); - } - } - - var publicModifier = SyntaxFactory.Token(SyntaxKind.PublicKeyword); - newModifiers = newModifiers.Insert(0, publicModifier); - node = node.WithModifiers(newModifiers); - return node; - } - } -} diff --git a/src/Components/Analyzers/src/ComponentSymbols.cs b/src/Components/Analyzers/src/ComponentSymbols.cs deleted file mode 100644 index d115e27f5389..000000000000 --- a/src/Components/Analyzers/src/ComponentSymbols.cs +++ /dev/null @@ -1,79 +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 Microsoft.CodeAnalysis; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - internal class ComponentSymbols - { - public static bool TryCreate(Compilation compilation, out ComponentSymbols symbols) - { - if (compilation == null) - { - throw new ArgumentNullException(nameof(compilation)); - } - - var parameterAttribute = compilation.GetTypeByMetadataName(ComponentsApi.ParameterAttribute.MetadataName); - if (parameterAttribute == null) - { - symbols = null; - return false; - } - - var cascadingParameterAttribute = compilation.GetTypeByMetadataName(ComponentsApi.CascadingParameterAttribute.MetadataName); - if (cascadingParameterAttribute == null) - { - symbols = null; - return false; - } - - var icomponentType = compilation.GetTypeByMetadataName(ComponentsApi.IComponent.MetadataName); - if (icomponentType == null) - { - symbols = null; - return false; - } - - var dictionary = compilation.GetTypeByMetadataName("System.Collections.Generic.Dictionary`2"); - var @string = compilation.GetSpecialType(SpecialType.System_String); - var @object = compilation.GetSpecialType(SpecialType.System_Object); - if (dictionary == null || @string == null || @object == null) - { - symbols = null; - return false; - } - - var parameterCaptureUnmatchedValuesRuntimeType = dictionary.Construct(@string, @object); - - symbols = new ComponentSymbols( - parameterAttribute, - cascadingParameterAttribute, - parameterCaptureUnmatchedValuesRuntimeType, - icomponentType); - return true; - } - - private ComponentSymbols( - INamedTypeSymbol parameterAttribute, - INamedTypeSymbol cascadingParameterAttribute, - INamedTypeSymbol parameterCaptureUnmatchedValuesRuntimeType, - INamedTypeSymbol icomponentType) - { - ParameterAttribute = parameterAttribute; - CascadingParameterAttribute = cascadingParameterAttribute; - ParameterCaptureUnmatchedValuesRuntimeType = parameterCaptureUnmatchedValuesRuntimeType; - IComponentType = icomponentType; - } - - public INamedTypeSymbol ParameterAttribute { get; } - - // Dictionary - public INamedTypeSymbol ParameterCaptureUnmatchedValuesRuntimeType { get; } - - public INamedTypeSymbol CascadingParameterAttribute { get; } - - public INamedTypeSymbol IComponentType { get; } - } -} diff --git a/src/Components/Analyzers/src/ComponentsApi.cs b/src/Components/Analyzers/src/ComponentsApi.cs deleted file mode 100644 index 73ceff39fd40..000000000000 --- a/src/Components/Analyzers/src/ComponentsApi.cs +++ /dev/null @@ -1,32 +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.Analyzers -{ - // Constants for type and method names used in code-generation - // Keep these in sync with the actual definitions - internal static class ComponentsApi - { - public static readonly string AssemblyName = "Microsoft.AspNetCore.Components"; - - public static class ParameterAttribute - { - public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.ParameterAttribute"; - public static readonly string MetadataName = FullTypeName; - - public static readonly string CaptureUnmatchedValues = "CaptureUnmatchedValues"; - } - - public static class CascadingParameterAttribute - { - public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.CascadingParameterAttribute"; - public static readonly string MetadataName = FullTypeName; - } - - public static class IComponent - { - public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.IComponent"; - public static readonly string MetadataName = FullTypeName; - } - } -} diff --git a/src/Components/Analyzers/src/DiagnosticDescriptors.cs b/src/Components/Analyzers/src/DiagnosticDescriptors.cs deleted file mode 100644 index 8eb86b3212fa..000000000000 --- a/src/Components/Analyzers/src/DiagnosticDescriptors.cs +++ /dev/null @@ -1,68 +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.CodeAnalysis; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - internal static class DiagnosticDescriptors - { - // Note: The Razor Compiler (including Components features) use the RZ prefix for diagnostics, so there's currently - // no change of clashing between that and the BL prefix used here. - // - // Tracking https://github.com/aspnet/AspNetCore/issues/10382 to rationalize this - public static readonly DiagnosticDescriptor ComponentParameterSettersShouldBePublic = new DiagnosticDescriptor( - "BL0001", - new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)), - "Encapsulation", - DiagnosticSeverity.Error, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources))); - - public static readonly DiagnosticDescriptor ComponentParameterCaptureUnmatchedValuesMustBeUnique = new DiagnosticDescriptor( - "BL0002", - new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesMustBeUnique_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesMustBeUnique_Format), Resources.ResourceManager, typeof(Resources)), - "Usage", - DiagnosticSeverity.Warning, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesMustBeUnique_Description), Resources.ResourceManager, typeof(Resources))); - - public static readonly DiagnosticDescriptor ComponentParameterCaptureUnmatchedValuesHasWrongType = new DiagnosticDescriptor( - "BL0003", - new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesHasWrongType_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesHasWrongType_Format), Resources.ResourceManager, typeof(Resources)), - "Usage", - DiagnosticSeverity.Warning, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.ComponentParameterCaptureUnmatchedValuesHasWrongType_Description), Resources.ResourceManager, typeof(Resources))); - - public static readonly DiagnosticDescriptor ComponentParametersShouldBePublic = new DiagnosticDescriptor( - "BL0004", - new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)), - "Encapsulation", - DiagnosticSeverity.Error, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.ComponentParametersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources))); - - public static readonly DiagnosticDescriptor ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent = new DiagnosticDescriptor( - "BL0005", - new LocalizableResourceString(nameof(Resources.ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Format), Resources.ResourceManager, typeof(Resources)), - "Usage", - DiagnosticSeverity.Warning, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Description), Resources.ResourceManager, typeof(Resources))); - - public static readonly DiagnosticDescriptor DoNotUseRenderTreeTypes = new DiagnosticDescriptor( - "BL0006", - new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Title), Resources.ResourceManager, typeof(Resources)), - new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources)), - "Usage", - DiagnosticSeverity.Warning, - isEnabledByDefault: true, - description: new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources))); - } -} diff --git a/src/Components/Analyzers/src/InternalUsageAnalyzer.cs b/src/Components/Analyzers/src/InternalUsageAnalyzer.cs deleted file mode 100644 index 92b07a7ab215..000000000000 --- a/src/Components/Analyzers/src/InternalUsageAnalyzer.cs +++ /dev/null @@ -1,126 +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 Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Microsoft.Extensions.Internal -{ - internal class InternalUsageAnalyzer - { - private readonly Func _isInternalNamespace; - private readonly Func _hasInternalAttribute; - private readonly DiagnosticDescriptor _descriptor; - - /// - /// Creates a new instance of . The creator should provide delegates to help determine whether - /// a given symbol is internal or not, and a to create errors. - /// - /// The delegate used to check if a symbol belongs to an internal namespace. - /// The delegate used to check if a symbol has an internal attribute. - /// - /// The used to create errors. The error message should expect a single parameter - /// used for the display name of the member. - /// - public InternalUsageAnalyzer(Func isInInternalNamespace, Func hasInternalAttribute, DiagnosticDescriptor descriptor) - { - _isInternalNamespace = isInInternalNamespace ?? new Func((_) => false); - _hasInternalAttribute = hasInternalAttribute ?? new Func((_) => false); - _descriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor)); - } - - public void Register(AnalysisContext context) - { - context.EnableConcurrentExecution(); - context.RegisterSyntaxNodeAction(AnalyzeNode, - SyntaxKind.SimpleMemberAccessExpression, - SyntaxKind.ObjectCreationExpression, - SyntaxKind.ClassDeclaration, - SyntaxKind.Parameter); - } - - private void AnalyzeNode(SyntaxNodeAnalysisContext context) - { - switch (context.Node) - { - case MemberAccessExpressionSyntax memberAccessSyntax: - { - if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol && - symbol.ContainingAssembly != context.Compilation.Assembly) - { - var containingType = symbol.ContainingType; - - if (HasInternalAttribute(symbol)) - { - context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), $"{containingType}.{symbol.Name}")); - return; - } - - if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType)) - { - context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), containingType)); - return; - } - } - return; - } - - case ObjectCreationExpressionSyntax creationSyntax: - { - if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol && - symbol.ContainingAssembly != context.Compilation.Assembly) - { - var containingType = symbol.ContainingType; - - if (HasInternalAttribute(symbol)) - { - context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.GetLocation(), containingType)); - return; - } - - if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType)) - { - context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.Type.GetLocation(), containingType)); - return; - } - } - - return; - } - - case ClassDeclarationSyntax declarationSyntax: - { - if (context.SemanticModel.GetDeclaredSymbol(declarationSyntax)?.BaseType is ISymbol symbol && - symbol.ContainingAssembly != context.Compilation.Assembly && - (IsInInternalNamespace(symbol) || HasInternalAttribute(symbol)) && - declarationSyntax.BaseList?.Types.Count > 0) - { - context.ReportDiagnostic(Diagnostic.Create(_descriptor, declarationSyntax.BaseList.Types[0].GetLocation(), symbol)); - } - - return; - } - - case ParameterSyntax parameterSyntax: - { - if (context.SemanticModel.GetDeclaredSymbol(parameterSyntax)?.Type is ISymbol symbol && - symbol.ContainingAssembly != context.Compilation.Assembly && - (IsInInternalNamespace(symbol) || HasInternalAttribute(symbol))) - { - - context.ReportDiagnostic(Diagnostic.Create(_descriptor, parameterSyntax.GetLocation(), symbol)); - } - - return; - } - } - } - - private bool HasInternalAttribute(ISymbol symbol) => _hasInternalAttribute(symbol); - - private bool IsInInternalNamespace(ISymbol symbol) => _isInternalNamespace(symbol); - } -} diff --git a/src/Components/Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj b/src/Components/Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj deleted file mode 100644 index a83904f24566..000000000000 --- a/src/Components/Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - netstandard2.0 - false - true - false - Roslyn analyzers for ASP.NET Core Components. - true - false - - - - - - - - - - - - - diff --git a/src/Components/Analyzers/src/Properties/AssemblyInfo.cs b/src/Components/Analyzers/src/Properties/AssemblyInfo.cs deleted file mode 100644 index 6e6689b592ac..000000000000 --- a/src/Components/Analyzers/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Analyzers.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Components/Analyzers/src/Resources.resx b/src/Components/Analyzers/src/Resources.resx deleted file mode 100644 index ed4f36c53195..000000000000 --- a/src/Components/Analyzers/src/Resources.resx +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Component parameters should have public setters. - - - Component parameter '{0}' should have a public setter. - - - Component parameter should have public setters. - - - Components may only define a single parameter with CaptureUnmatchedValues. - - - Component type '{0}' defines properties multiple parameters with CaptureUnmatchedValues. Properties: {1}{2} - - - Component has multiple CaptureUnmatchedValues parameters - - - Component parameters with CaptureUnmatchedValues must be a correct type. - - - Component parameter '{0}' defines CaptureUnmatchedValues but has an unsupported type '{1}'. Use a type assignable from '{2}'. - - - Component parameter with CaptureUnmatchedValues has the wrong type - - - Component parameter '{0}' should be public. - - - Component parameter should be public. - - - Component parameters should be public. - - - Make component parameters public. - - - Component parameters should not be set outside of their declared component. Doing so may result in unexpected behavior at runtime. - - - Component parameter '{0}' should not be set outside of its component. - - - Component parameter should not be set outside of its component. - - - The types in 'Microsoft.AspNetCore.Components.RenderTree' are not recommended for use outside of the Blazor framework. These type definitions will change in future releases. - - - The type or member {0} is is not recommended for use outside of the Blazor frameworks. Types defined in 'Microsoft.AspNetCore.Components.RenderTree' will change in future releases. - - - Do not use RenderTree types - - \ No newline at end of file diff --git a/src/Components/Analyzers/src/build/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.props b/src/Components/Analyzers/src/build/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.props deleted file mode 100644 index 0ba7b4da050d..000000000000 --- a/src/Components/Analyzers/src/build/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.props +++ /dev/null @@ -1,5 +0,0 @@ - - - true - - diff --git a/src/Components/Analyzers/test/AnalyzerTestBase.cs b/src/Components/Analyzers/test/AnalyzerTestBase.cs deleted file mode 100644 index 8c1ae953762e..000000000000 --- a/src/Components/Analyzers/test/AnalyzerTestBase.cs +++ /dev/null @@ -1,67 +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.Threading.Tasks; -using Microsoft.AspNetCore.Analyzer.Testing; -using Microsoft.AspNetCore.Testing; -using Microsoft.CodeAnalysis; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public abstract class AnalyzerTestBase - { - private static readonly string ProjectDirectory = GetProjectDirectory(); - - public TestSource Read(string source) - { - if (!source.EndsWith(".cs")) - { - source = source + ".cs"; - } - - var filePath = Path.Combine(ProjectDirectory, "TestFiles", GetType().Name, source); - if (!File.Exists(filePath)) - { - throw new FileNotFoundException($"TestFile {source} could not be found at {filePath}.", filePath); - } - - var fileContent = File.ReadAllText(filePath); - return TestSource.Read(fileContent); - } - - public Project CreateProject(string source) - { - if (!source.EndsWith(".cs")) - { - source = source + ".cs"; - } - - var read = Read(source); - return DiagnosticProject.Create(GetType().Assembly, new[] { read.Source, }); - } - - public Task CreateCompilationAsync(string source) - { - return CreateProject(source).GetCompilationAsync(); - } - - private static string GetProjectDirectory() - { - // On helix we use the published test files - if (SkipOnHelixAttribute.OnHelix()) - { - return AppContext.BaseDirectory; - } - - // This test code needs to be updated to support distributed testing. - // See https://github.com/aspnet/AspNetCore/issues/10422 -#pragma warning disable 0618 - var solutionDirectory = TestPathUtilities.GetSolutionRootDirectory("Components"); -#pragma warning restore 0618 - var projectDirectory = Path.Combine(solutionDirectory, "Analyzers", "test"); - return projectDirectory; - } - } -} diff --git a/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs b/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs deleted file mode 100644 index 727f060bd463..000000000000 --- a/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs +++ /dev/null @@ -1,31 +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.Threading.Tasks; -using Microsoft.AspNetCore.Analyzer.Testing; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - internal class ComponentAnalyzerDiagnosticAnalyzerRunner : DiagnosticAnalyzerRunner - { - public ComponentAnalyzerDiagnosticAnalyzerRunner(DiagnosticAnalyzer analyzer) - { - Analyzer = analyzer; - } - - public DiagnosticAnalyzer Analyzer { get; } - - public Task GetDiagnosticsAsync(string source) - { - return GetDiagnosticsAsync(sources: new[] { source }, Analyzer, Array.Empty()); - } - - public Task GetDiagnosticsAsync(Project project) - { - return GetDiagnosticsAsync(new[] { project }, Analyzer, Array.Empty()); - } - } -} diff --git a/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs b/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs deleted file mode 100644 index 92e2252304af..000000000000 --- a/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs +++ /dev/null @@ -1,60 +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.Threading.Tasks; -using Microsoft.AspNetCore.Analyzer.Testing; -using Microsoft.Extensions.Internal; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public class ComponentInternalUsageDiagnoticsAnalyzerTest : AnalyzerTestBase - { - public ComponentInternalUsageDiagnoticsAnalyzerTest() - { - Analyzer = new ComponentInternalUsageDiagnosticAnalyzer(); - Runner = new ComponentAnalyzerDiagnosticAnalyzerRunner(Analyzer); - } - - private ComponentInternalUsageDiagnosticAnalyzer Analyzer { get; } - private ComponentAnalyzerDiagnosticAnalyzerRunner Runner { get; } - - [Fact] - public async Task InternalUsage_FindsUseOfRenderTreeFrameAsParameter() - { - // Arrange - var source = Read("UsesRenderTreeFrameAsParameter"); - - // Act - var diagnostics = await Runner.GetDiagnosticsAsync(source.Source); - - // Assert - Assert.Collection( - diagnostics, - diagnostic => - { - Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor); - AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - }); - } - - [Fact] - public async Task InternalUsage_FindsUseOfRenderTreeType() - { - // Arrange - var source = Read("UsesRenderTreeFrameTypeAsLocal"); - - // Act - var diagnostics = await Runner.GetDiagnosticsAsync(source.Source); - - // Assert - Assert.Collection( - diagnostics, - diagnostic => - { - Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor); - AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - }); - } - } -} diff --git a/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesHasWrongTypeTest.cs b/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesHasWrongTypeTest.cs deleted file mode 100644 index e4673c374799..000000000000 --- a/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesHasWrongTypeTest.cs +++ /dev/null @@ -1,80 +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.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers.Test -{ - public class ComponentParameterCaptureUnmatchedValuesHasWrongTypeTest : DiagnosticVerifier - { - [Theory] - [InlineData("System.Collections.Generic.IEnumerable>")] - [InlineData("System.Collections.Generic.Dictionary")] - [InlineData("System.Collections.Generic.IDictionary")] - [InlineData("System.Collections.Generic.IReadOnlyDictionary")] - public void IgnoresPropertiesWithSupportedType(string propertyType) - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter(CaptureUnmatchedValues = true)] public {propertyType} MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void IgnoresPropertiesWithCaptureUnmatchedValuesFalse() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter(CaptureUnmatchedValues = false)] public string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void AddsDiagnosticForInvalidType() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter(CaptureUnmatchedValues = true)] public string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesHasWrongType.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty' defines CaptureUnmatchedValues but has an unsupported type 'string'. Use a type assignable from 'System.Collections.Generic.Dictionary'.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 7, 70) - } - }); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() - { - return new ComponentParameterAnalyzer(); - } - } -} diff --git a/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesMustBeUniqueTest.cs b/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesMustBeUniqueTest.cs deleted file mode 100644 index f7b055caa7ca..000000000000 --- a/src/Components/Analyzers/test/ComponentParameterCaptureUnmatchedValuesMustBeUniqueTest.cs +++ /dev/null @@ -1,69 +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 Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers.Test -{ - public class ComponentParameterCaptureUnmatchedValuesMustBeUniqueTest : DiagnosticVerifier - { - [Fact] - public void IgnoresPropertiesWithCaptureUnmatchedValuesFalse() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using System.Collections.Generic; - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter(CaptureUnmatchedValues = false)] public string MyProperty {{ get; set; }} - [Parameter(CaptureUnmatchedValues = true)] public Dictionary MyOtherProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void AddsDiagnosticForMultipleCaptureUnmatchedValuesProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using System.Collections.Generic; - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter(CaptureUnmatchedValues = true)] public Dictionary MyProperty {{ get; set; }} - [Parameter(CaptureUnmatchedValues = true)] public Dictionary MyOtherProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - var message = @"Component type 'ConsoleApplication1.TypeName' defines properties multiple parameters with CaptureUnmatchedValues. Properties: " + Environment.NewLine + -"ConsoleApplication1.TypeName.MyOtherProperty" + Environment.NewLine + -"ConsoleApplication1.TypeName.MyProperty"; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterCaptureUnmatchedValuesMustBeUnique.Id, - Message = message, - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 6, 15) - } - }); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() - { - return new ComponentParameterAnalyzer(); - } - } -} diff --git a/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs b/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs deleted file mode 100644 index f32bc6048e45..000000000000 --- a/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs +++ /dev/null @@ -1,111 +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.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public class ComponentParameterSettersShouldBePublicTest : DiagnosticVerifier - { - [Fact] - public void IgnoresCascadingParameterProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(CascadingParameterAttribute).Namespace}; - class TypeName - {{ - [CascadingParameter] string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void IgnoresPublicSettersProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter] public string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void IgnoresPrivateSettersNonParameterProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - private string MyProperty {{ get; private set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ErrorsForNonPublicSetterParameters() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter] public string MyProperty1 {{ get; private set; }} - [Parameter] public string MyProperty2 {{ get; protected set; }} - [Parameter] public string MyProperty3 {{ get; internal set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 7, 39) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 8, 39) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 9, 39) - } - }); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() => new ComponentParameterAnalyzer(); - } -} diff --git a/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs b/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs deleted file mode 100644 index d1c2d2bede4b..000000000000 --- a/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs +++ /dev/null @@ -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 Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public class ComponentParameterUsageAnalyzerTest : DiagnosticVerifier - { - public ComponentParameterUsageAnalyzerTest() - { - ComponentTestSource = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TestComponent : IComponent - {{ - [Parameter] public string TestProperty {{ get; set; }} - [Parameter] public int TestInt {{ get; set; }} - public string NonParameter {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - } - - private string ComponentTestSource { get; } - - [Fact] - public void ComponentPropertySimpleAssignment_Warns() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.TestProperty = ""Hello World""; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id, - Message = "Component parameter 'TestProperty' should not be set outside of its component.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 11, 17) - } - }); - } - - [Fact] - public void ComponentPropertyCoalesceAssignment__Warns() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.TestProperty ??= ""Hello World""; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id, - Message = "Component parameter 'TestProperty' should not be set outside of its component.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 11, 17) - } - }); - } - - [Fact] - public void ComponentPropertyCompoundAssignment__Warns() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.TestProperty += ""Hello World""; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id, - Message = "Component parameter 'TestProperty' should not be set outside of its component.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 11, 17) - } - }); - } - - [Fact] - public void ComponentPropertyIncrement_Warns() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.TestInt++; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id, - Message = "Component parameter 'TestInt' should not be set outside of its component.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 11, 17) - } - }); - } - - [Fact] - public void ComponentPropertyDecrement_Warns() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.TestInt--; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id, - Message = "Component parameter 'TestInt' should not be set outside of its component.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 11, 17) - } - }); - } - - [Fact] - public void ComponentPropertyExpression_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - void Method() - {{ - System.IO.Console.WriteLine(new TestComponent().TestProperty); - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ComponentPropertyExpressionInStatement_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - void Method() - {{ - var testComponent = new TestComponent(); - for (var i = 0; i < testComponent.TestProperty.Length; i++) - {{ - }} - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void RetrievalOfComponentPropertyValueInAssignment_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - void Method() - {{ - var testComponent = new TestComponent(); - AnotherProperty = testComponent.TestProperty; - }} - - public string AnotherProperty {{ get; set; }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ShadowedComponentPropertyAssignment_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - void Method() - {{ - var testComponent = new InheritedComponent(); - testComponent.TestProperty = ""Hello World""; - }} - }} - - class InheritedComponent : TestComponent - {{ - public new string TestProperty {{ get; set; }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void InheritedImplicitComponentPropertyAssignment_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName : TestComponent - {{ - void Method() - {{ - this.TestProperty = ""Hello World""; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ImplicitComponentPropertyAssignment_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName : IComponent - {{ - void Method() - {{ - TestProperty = ""Hello World""; - }} - - [Parameter] public string TestProperty {{ get; set; }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ComponentPropertyAssignment_NonParameter_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private TestComponent _testComponent; - void Render() - {{ - _testComponent = new TestComponent(); - _testComponent.NonParameter = ""Hello World""; - }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void NonComponentPropertyAssignment_Ignores() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class OtherComponent : IComponent - {{ - private SomethingElse _testNonComponent; - void Render() - {{ - _testNonComponent = new NotAComponent(); - _testNonComponent.TestProperty = ""Hello World""; - }} - }} - class NotAComponent - {{ - [Parameter] public string TestProperty {{ get; set; }} - }} - }}" + ComponentTestSource; - - VerifyCSharpDiagnostic(test); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() => new ComponentParameterUsageAnalyzer(); - } -} diff --git a/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs b/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs deleted file mode 100644 index 2e1ee00be08b..000000000000 --- a/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs +++ /dev/null @@ -1,126 +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.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers.Test -{ - public class ComponentParametersShouldBePublicCodeFixProviderTest : CodeFixVerifier - { - [Fact] - public void IgnoresPrivatePropertiesWithoutParameterAttribute() - { - var test = @" - namespace ConsoleApplication1 - { - class TypeName - { - private string MyProperty { get; set; } - } - }" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void AddsDiagnosticAndFixForPrivatePropertiesWithParameterAttribute() - { - var test = @" - namespace ConsoleApplication1 - { - using " + typeof(ParameterAttribute).Namespace + @"; - - class TypeName - { - [Parameter] private string BadProperty1 { get; set; } - } - }" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.BadProperty1' should be public.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 8, 40) - } - }); - - VerifyCSharpFix(test, @" - namespace ConsoleApplication1 - { - using " + typeof(ParameterAttribute).Namespace + @"; - - class TypeName - { - [Parameter] public string BadProperty1 { get; set; } - } - }" + ComponentsTestDeclarations.Source); - } - - [Fact] - public void IgnoresPublicPropertiesWithNonPublicSetterWithParameterAttribute() - { - var test = @" - namespace ConsoleApplication1 - { - using " + typeof(ParameterAttribute).Namespace + @"; - - class TypeName - { - [Parameter] public string MyProperty1 { get; private set; } - [Parameter] public object MyProperty2 { get; protected set; } - [Parameter] public object MyProperty3 { get; internal set; } - } - }" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 8, 39) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 9, 39) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 10, 39) - } - }); - } - - protected override CodeFixProvider GetCSharpCodeFixProvider() - { - return new ComponentParametersShouldBePublicCodeFixProvider(); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() - { - return new ComponentParameterAnalyzer(); - } - } -} diff --git a/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs b/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs deleted file mode 100644 index 97b01c469948..000000000000 --- a/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs +++ /dev/null @@ -1,106 +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.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using TestHelper; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public class ComponentParametersShouldBePublicTest : DiagnosticVerifier - { - [Fact] - public void IgnoresPublicProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter] public string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void IgnoresPrivateNonParameterProperties() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - private string MyProperty {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test); - } - - [Fact] - public void ErrorsForNonPublicParameters() - { - var test = $@" - namespace ConsoleApplication1 - {{ - using {typeof(ParameterAttribute).Namespace}; - class TypeName - {{ - [Parameter] string MyProperty1 {{ get; set; }} - [Parameter] private string MyProperty2 {{ get; set; }} - [Parameter] protected string MyProperty3 {{ get; set; }} - [Parameter] internal string MyProperty4 {{ get; set; }} - }} - }}" + ComponentsTestDeclarations.Source; - - VerifyCSharpDiagnostic(test, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should be public.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 7, 32) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should be public.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 8, 40) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should be public.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 9, 42) - } - }, - new DiagnosticResult - { - Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, - Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty4' should be public.", - Severity = DiagnosticSeverity.Error, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", 10, 41) - } - }); - } - - protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() => new ComponentParameterAnalyzer(); - } -} diff --git a/src/Components/Analyzers/test/ComponentsTestDeclarations.cs b/src/Components/Analyzers/test/ComponentsTestDeclarations.cs deleted file mode 100644 index 3c71a825660d..000000000000 --- a/src/Components/Analyzers/test/ComponentsTestDeclarations.cs +++ /dev/null @@ -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. - -namespace Microsoft.AspNetCore.Components.Analyzers -{ - public static class ComponentsTestDeclarations - { - public static readonly string Source = $@" - namespace {typeof(ParameterAttribute).Namespace} - {{ - public class {typeof(ParameterAttribute).Name} : System.Attribute - {{ - public bool CaptureUnmatchedValues {{ get; set; }} - }} - - public class {typeof(CascadingParameterAttribute).Name} : System.Attribute - {{ - }} - - public interface {typeof(IComponent).Name} - {{ - }} - }} -"; - } -} diff --git a/src/Components/Analyzers/test/Helpers/CodeFixVerifier.Helper.cs b/src/Components/Analyzers/test/Helpers/CodeFixVerifier.Helper.cs deleted file mode 100644 index b523daa09b12..000000000000 --- a/src/Components/Analyzers/test/Helpers/CodeFixVerifier.Helper.cs +++ /dev/null @@ -1,90 +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. - -// Most of the code in this file comes from the default Roslyn Analyzer project template - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Simplification; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -namespace TestHelper -{ - /// - /// Diagnostic Producer class with extra methods dealing with applying codefixes - /// All methods are static - /// - public abstract partial class CodeFixVerifier : DiagnosticVerifier - { - /// - /// Apply the inputted CodeAction to the inputted document. - /// Meant to be used to apply codefixes. - /// - /// The Document to apply the fix on - /// A CodeAction that will be applied to the Document. - /// A Document with the changes from the CodeAction - private static Document ApplyFix(Document document, CodeAction codeAction) - { - var operations = codeAction.GetOperationsAsync(CancellationToken.None).Result; - var solution = operations.OfType().Single().ChangedSolution; - return solution.GetDocument(document.Id); - } - - /// - /// Compare two collections of Diagnostics,and return a list of any new diagnostics that appear only in the second collection. - /// Note: Considers Diagnostics to be the same if they have the same Ids. In the case of multiple diagnostics with the same Id in a row, - /// this method may not necessarily return the new one. - /// - /// The Diagnostics that existed in the code before the CodeFix was applied - /// The Diagnostics that exist in the code after the CodeFix was applied - /// A list of Diagnostics that only surfaced in the code after the CodeFix was applied - private static IEnumerable GetNewDiagnostics(IEnumerable diagnostics, IEnumerable newDiagnostics) - { - var oldArray = diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); - var newArray = newDiagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); - - int oldIndex = 0; - int newIndex = 0; - - while (newIndex < newArray.Length) - { - if (oldIndex < oldArray.Length && oldArray[oldIndex].Id == newArray[newIndex].Id) - { - ++oldIndex; - ++newIndex; - } - else - { - yield return newArray[newIndex++]; - } - } - } - - /// - /// Get the existing compiler diagnostics on the inputted document. - /// - /// The Document to run the compiler diagnostic analyzers on - /// The compiler diagnostics that were found in the code - private static IEnumerable GetCompilerDiagnostics(Document document) - { - return document.GetSemanticModelAsync().Result.GetDiagnostics(); - } - - /// - /// Given a document, turn it into a string based on the syntax root - /// - /// The Document to be converted to a string - /// A string containing the syntax of the Document after formatting - private static string GetStringFromDocument(Document document) - { - var simplifiedDoc = Simplifier.ReduceAsync(document, Simplifier.Annotation).Result; - var root = simplifiedDoc.GetSyntaxRootAsync().Result; - root = Formatter.Format(root, Formatter.Annotation, simplifiedDoc.Project.Solution.Workspace); - return root.GetText().ToString(); - } - } -} - diff --git a/src/Components/Analyzers/test/Helpers/DiagnosticResult.cs b/src/Components/Analyzers/test/Helpers/DiagnosticResult.cs deleted file mode 100644 index 4e3349ae2592..000000000000 --- a/src/Components/Analyzers/test/Helpers/DiagnosticResult.cs +++ /dev/null @@ -1,92 +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. - -// Most of the code in this file comes from the default Roslyn Analyzer project template - -using Microsoft.CodeAnalysis; -using System; - -namespace TestHelper -{ - /// - /// Location where the diagnostic appears, as determined by path, line number, and column number. - /// - public struct DiagnosticResultLocation - { - public DiagnosticResultLocation(string path, int line, int column) - { - if (line < -1) - { - throw new ArgumentOutOfRangeException(nameof(line), "line must be >= -1"); - } - - if (column < -1) - { - throw new ArgumentOutOfRangeException(nameof(column), "column must be >= -1"); - } - - this.Path = path; - this.Line = line; - this.Column = column; - } - - public string Path { get; } - public int Line { get; } - public int Column { get; } - } - - /// - /// Struct that stores information about a Diagnostic appearing in a source - /// - public struct DiagnosticResult - { - private DiagnosticResultLocation[] locations; - - public DiagnosticResultLocation[] Locations - { - get - { - if (this.locations == null) - { - this.locations = new DiagnosticResultLocation[] { }; - } - return this.locations; - } - - set - { - this.locations = value; - } - } - - public DiagnosticSeverity Severity { get; set; } - - public string Id { get; set; } - - public string Message { get; set; } - - public string Path - { - get - { - return this.Locations.Length > 0 ? this.Locations[0].Path : ""; - } - } - - public int Line - { - get - { - return this.Locations.Length > 0 ? this.Locations[0].Line : -1; - } - } - - public int Column - { - get - { - return this.Locations.Length > 0 ? this.Locations[0].Column : -1; - } - } - } -} diff --git a/src/Components/Analyzers/test/Helpers/DiagnosticVerifier.Helper.cs b/src/Components/Analyzers/test/Helpers/DiagnosticVerifier.Helper.cs deleted file mode 100644 index b55bf99cf4a4..000000000000 --- a/src/Components/Analyzers/test/Helpers/DiagnosticVerifier.Helper.cs +++ /dev/null @@ -1,175 +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. - -// Most of the code in this file comes from the default Roslyn Analyzer project template - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Text; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace TestHelper -{ - /// - /// Class for turning strings into documents and getting the diagnostics on them - /// All methods are static - /// - public abstract partial class DiagnosticVerifier - { - private static readonly MetadataReference CorlibReference = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); - private static readonly MetadataReference SystemCoreReference = MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location); - private static readonly MetadataReference CSharpSymbolsReference = MetadataReference.CreateFromFile(typeof(CSharpCompilation).Assembly.Location); - private static readonly MetadataReference CodeAnalysisReference = MetadataReference.CreateFromFile(typeof(Compilation).Assembly.Location); - - internal static string DefaultFilePathPrefix = "Test"; - internal static string CSharpDefaultFileExt = "cs"; - internal static string VisualBasicDefaultExt = "vb"; - internal static string TestProjectName = "TestProject"; - - #region Get Diagnostics - - /// - /// Given classes in the form of strings, their language, and an IDiagnosticAnalyzer to apply to it, return the diagnostics found in the string after converting it to a document. - /// - /// Classes in the form of strings - /// The language the source classes are in - /// The analyzer to be run on the sources - /// An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location - private static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer) - { - return GetSortedDiagnosticsFromDocuments(analyzer, GetDocuments(sources, language)); - } - - /// - /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it. - /// The returned diagnostics are then ordered by location in the source document. - /// - /// The analyzer to run on the documents - /// The Documents that the analyzer will be run on - /// An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location - protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer analyzer, Document[] documents) - { - var projects = new HashSet(); - foreach (var document in documents) - { - projects.Add(document.Project); - } - - var diagnostics = new List(); - foreach (var project in projects) - { - var compilationWithAnalyzers = project.GetCompilationAsync().Result.WithAnalyzers(ImmutableArray.Create(analyzer)); - var diags = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result; - foreach (var diag in diags) - { - if (diag.Location == Location.None || diag.Location.IsInMetadata) - { - diagnostics.Add(diag); - } - else - { - for (int i = 0; i < documents.Length; i++) - { - var document = documents[i]; - var tree = document.GetSyntaxTreeAsync().Result; - if (tree == diag.Location.SourceTree) - { - diagnostics.Add(diag); - } - } - } - } - } - - var results = SortDiagnostics(diagnostics); - diagnostics.Clear(); - return results; - } - - /// - /// Sort diagnostics by location in source document - /// - /// The list of Diagnostics to be sorted - /// An IEnumerable containing the Diagnostics in order of Location - private static Diagnostic[] SortDiagnostics(IEnumerable diagnostics) - { - return diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); - } - - #endregion - - #region Set up compilation and documents - /// - /// Given an array of strings as sources and a language, turn them into a project and return the documents and spans of it. - /// - /// Classes in the form of strings - /// The language the source code is in - /// A Tuple containing the Documents produced from the sources and their TextSpans if relevant - private static Document[] GetDocuments(string[] sources, string language) - { - if (language != LanguageNames.CSharp && language != LanguageNames.VisualBasic) - { - throw new ArgumentException("Unsupported Language"); - } - - var project = CreateProject(sources, language); - var documents = project.Documents.ToArray(); - - if (sources.Length != documents.Length) - { - throw new InvalidOperationException("Amount of sources did not match amount of Documents created"); - } - - return documents; - } - - /// - /// Create a Document from a string through creating a project that contains it. - /// - /// Classes in the form of a string - /// The language the source code is in - /// A Document created from the source string - protected static Document CreateDocument(string source, string language = LanguageNames.CSharp) - { - return CreateProject(new[] { source }, language).Documents.First(); - } - - /// - /// Create a project using the inputted strings as sources. - /// - /// Classes in the form of strings - /// The language the source code is in - /// A Project created out of the Documents created from the source strings - private static Project CreateProject(string[] sources, string language = LanguageNames.CSharp) - { - string fileNamePrefix = DefaultFilePathPrefix; - string fileExt = language == LanguageNames.CSharp ? CSharpDefaultFileExt : VisualBasicDefaultExt; - - var projectId = ProjectId.CreateNewId(debugName: TestProjectName); - - var solution = new AdhocWorkspace() - .CurrentSolution - .AddProject(projectId, TestProjectName, TestProjectName, language) - .AddMetadataReference(projectId, CorlibReference) - .AddMetadataReference(projectId, SystemCoreReference) - .AddMetadataReference(projectId, CSharpSymbolsReference) - .AddMetadataReference(projectId, CodeAnalysisReference); - - int count = 0; - foreach (var source in sources) - { - var newFileName = fileNamePrefix + count + "." + fileExt; - var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName); - solution = solution.AddDocument(documentId, newFileName, SourceText.From(source)); - count++; - } - return solution.GetProject(projectId); - } - #endregion - } -} - diff --git a/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj b/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj deleted file mode 100644 index 10085017d1f8..000000000000 --- a/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - - - - false - - - - - - - - - - - - - - - - - diff --git a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs deleted file mode 100644 index 415030a01166..000000000000 --- a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest -{ - class UsesRenderTreeFrameAsParameter - { - private void Test(/*MM*/RenderTreeFrame frame) - { - } - } -} diff --git a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs deleted file mode 100644 index bdd40c2df1ef..000000000000 --- a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest -{ - class UsesRenderTreeFrameTypeAsLocal - { - private void Test() - { - var test = RenderTreeFrameType./*MM*/Attribute; - GC.KeepAlive(test); - } - - } -} diff --git a/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs b/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs deleted file mode 100644 index cb6c9d432992..000000000000 --- a/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs +++ /dev/null @@ -1,133 +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. - -// Most of the code in this file comes from the default Roslyn Analyzer project template - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Formatting; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using Xunit; - -namespace TestHelper -{ - /// - /// Superclass of all Unit tests made for diagnostics with codefixes. - /// Contains methods used to verify correctness of codefixes - /// - public abstract partial class CodeFixVerifier : DiagnosticVerifier - { - /// - /// Returns the codefix being tested (C#) - to be implemented in non-abstract class - /// - /// The CodeFixProvider to be used for CSharp code - protected virtual CodeFixProvider GetCSharpCodeFixProvider() - { - return null; - } - - /// - /// Returns the codefix being tested (VB) - to be implemented in non-abstract class - /// - /// The CodeFixProvider to be used for VisualBasic code - protected virtual CodeFixProvider GetBasicCodeFixProvider() - { - return null; - } - - /// - /// Called to test a C# codefix when applied on the inputted string as a source - /// - /// A class in the form of a string before the CodeFix was applied to it - /// A class in the form of a string after the CodeFix was applied to it - /// Index determining which codefix to apply if there are multiple - /// A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied - protected void VerifyCSharpFix(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false) - { - VerifyFix(LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), GetCSharpCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics); - } - - /// - /// Called to test a VB codefix when applied on the inputted string as a source - /// - /// A class in the form of a string before the CodeFix was applied to it - /// A class in the form of a string after the CodeFix was applied to it - /// Index determining which codefix to apply if there are multiple - /// A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied - protected void VerifyBasicFix(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false) - { - VerifyFix(LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), GetBasicCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics); - } - - /// - /// General verifier for codefixes. - /// Creates a Document from the source string, then gets diagnostics on it and applies the relevant codefixes. - /// Then gets the string after the codefix is applied and compares it with the expected result. - /// Note: If any codefix causes new diagnostics to show up, the test fails unless allowNewCompilerDiagnostics is set to true. - /// - /// The language the source code is in - /// The analyzer to be applied to the source code - /// The codefix to be applied to the code wherever the relevant Diagnostic is found - /// A class in the form of a string before the CodeFix was applied to it - /// A class in the form of a string after the CodeFix was applied to it - /// Index determining which codefix to apply if there are multiple - /// A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied - private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics) - { - var document = CreateDocument(oldSource, language); - var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); - var compilerDiagnostics = GetCompilerDiagnostics(document); - var attempts = analyzerDiagnostics.Length; - - for (int i = 0; i < attempts; ++i) - { - var actions = new List(); - var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None); - codeFixProvider.RegisterCodeFixesAsync(context).Wait(); - - if (!actions.Any()) - { - break; - } - - if (codeFixIndex != null) - { - document = ApplyFix(document, actions.ElementAt((int)codeFixIndex)); - break; - } - - document = ApplyFix(document, actions.ElementAt(0)); - analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); - - var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document)); - - //check if applying the code fix introduced any new compiler diagnostics - if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any()) - { - // Format and get the compiler diagnostics again so that the locations make sense in the output - document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace)); - newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document)); - - Assert.True(false, - string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n", - string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())), - document.GetSyntaxRootAsync().Result.ToFullString())); - } - - //check if there are analyzer diagnostics left after the code fix - if (!analyzerDiagnostics.Any()) - { - break; - } - } - - //after applying all of the code fixes, compare the resulting string to the inputted one - var actual = GetStringFromDocument(document); - Assert.Equal(newSource, actual); - } - } -} diff --git a/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs b/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs deleted file mode 100644 index f56d4ff93d74..000000000000 --- a/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs +++ /dev/null @@ -1,274 +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. - -// Most of the code in this file comes from the default Roslyn Analyzer project template - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Xunit; - -namespace TestHelper -{ - /// - /// Superclass of all Unit Tests for DiagnosticAnalyzers - /// - public abstract partial class DiagnosticVerifier - { - #region To be implemented by Test classes - /// - /// Get the CSharp analyzer being tested - to be implemented in non-abstract class - /// - protected virtual DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() - { - return null; - } - - /// - /// Get the Visual Basic analyzer being tested (C#) - to be implemented in non-abstract class - /// - protected virtual DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() - { - return null; - } - #endregion - - #region Verifier wrappers - - /// - /// Called to test a C# DiagnosticAnalyzer when applied on the single inputted string as a source - /// Note: input a DiagnosticResult for each Diagnostic expected - /// - /// A class in the form of a string to run the analyzer on - /// DiagnosticResults that should appear after the analyzer is run on the source - protected void VerifyCSharpDiagnostic(string source, params DiagnosticResult[] expected) - { - VerifyDiagnostics(new[] { source }, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), expected); - } - - /// - /// Called to test a VB DiagnosticAnalyzer when applied on the single inputted string as a source - /// Note: input a DiagnosticResult for each Diagnostic expected - /// - /// A class in the form of a string to run the analyzer on - /// DiagnosticResults that should appear after the analyzer is run on the source - protected void VerifyBasicDiagnostic(string source, params DiagnosticResult[] expected) - { - VerifyDiagnostics(new[] { source }, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), expected); - } - - /// - /// Called to test a C# DiagnosticAnalyzer when applied on the inputted strings as a source - /// Note: input a DiagnosticResult for each Diagnostic expected - /// - /// An array of strings to create source documents from to run the analyzers on - /// DiagnosticResults that should appear after the analyzer is run on the sources - protected void VerifyCSharpDiagnostic(string[] sources, params DiagnosticResult[] expected) - { - VerifyDiagnostics(sources, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), expected); - } - - /// - /// Called to test a VB DiagnosticAnalyzer when applied on the inputted strings as a source - /// Note: input a DiagnosticResult for each Diagnostic expected - /// - /// An array of strings to create source documents from to run the analyzers on - /// DiagnosticResults that should appear after the analyzer is run on the sources - protected void VerifyBasicDiagnostic(string[] sources, params DiagnosticResult[] expected) - { - VerifyDiagnostics(sources, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), expected); - } - - /// - /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run, - /// then verifies each of them. - /// - /// An array of strings to create source documents from to run the analyzers on - /// The language of the classes represented by the source strings - /// The analyzer to be run on the source code - /// DiagnosticResults that should appear after the analyzer is run on the sources - private void VerifyDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected) - { - var diagnostics = GetSortedDiagnostics(sources, language, analyzer); - VerifyDiagnosticResults(diagnostics, analyzer, expected); - } - - #endregion - - #region Actual comparisons and verifications - /// - /// Checks each of the actual Diagnostics found and compares them with the corresponding DiagnosticResult in the array of expected results. - /// Diagnostics are considered equal only if the DiagnosticResultLocation, Id, Severity, and Message of the DiagnosticResult match the actual diagnostic. - /// - /// The Diagnostics found by the compiler after running the analyzer on the source code - /// The analyzer that was being run on the sources - /// Diagnostic Results that should have appeared in the code - private static void VerifyDiagnosticResults(IEnumerable actualResults, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expectedResults) - { - int expectedCount = expectedResults.Count(); - int actualCount = actualResults.Count(); - - if (expectedCount != actualCount) - { - string diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults.ToArray()) : " NONE."; - - Assert.True(false, - string.Format("Mismatch between number of diagnostics returned, expected \"{0}\" actual \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput)); - } - - for (int i = 0; i < expectedResults.Length; i++) - { - var actual = actualResults.ElementAt(i); - var expected = expectedResults[i]; - - if (expected.Line == -1 && expected.Column == -1) - { - if (actual.Location != Location.None) - { - Assert.True(false, - string.Format("Expected:\nA project diagnostic with No location\nActual:\n{0}", - FormatDiagnostics(analyzer, actual))); - } - } - else - { - VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Locations.First()); - var additionalLocations = actual.AdditionalLocations.ToArray(); - - if (additionalLocations.Length != expected.Locations.Length - 1) - { - Assert.True(false, - string.Format("Expected {0} additional locations but got {1} for Diagnostic:\r\n {2}\r\n", - expected.Locations.Length - 1, additionalLocations.Length, - FormatDiagnostics(analyzer, actual))); - } - - for (int j = 0; j < additionalLocations.Length; ++j) - { - VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Locations[j + 1]); - } - } - - if (actual.Id != expected.Id) - { - Assert.True(false, - string.Format("Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Id, actual.Id, FormatDiagnostics(analyzer, actual))); - } - - if (actual.Severity != expected.Severity) - { - Assert.True(false, - string.Format("Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual))); - } - - if (actual.GetMessage() != expected.Message) - { - Assert.True(false, - string.Format("Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual))); - } - } - } - - /// - /// Helper method to VerifyDiagnosticResult that checks the location of a diagnostic and compares it with the location in the expected DiagnosticResult. - /// - /// The analyzer that was being run on the sources - /// The diagnostic that was found in the code - /// The Location of the Diagnostic found in the code - /// The DiagnosticResultLocation that should have been found - private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, Location actual, DiagnosticResultLocation expected) - { - var actualSpan = actual.GetLineSpan(); - - Assert.True(actualSpan.Path == expected.Path || (actualSpan.Path != null && actualSpan.Path.Contains("Test0.") && expected.Path.Contains("Test.")), - string.Format("Expected diagnostic to be in file \"{0}\" was actually in file \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Path, actualSpan.Path, FormatDiagnostics(analyzer, diagnostic))); - - var actualLinePosition = actualSpan.StartLinePosition; - - // Only check line position if there is an actual line in the real diagnostic - if (actualLinePosition.Line > 0) - { - if (actualLinePosition.Line + 1 != expected.Line) - { - Assert.True(false, - string.Format("Expected diagnostic to be on line \"{0}\" was actually on line \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Line, actualLinePosition.Line + 1, FormatDiagnostics(analyzer, diagnostic))); - } - } - - // Only check column position if there is an actual column position in the real diagnostic - if (actualLinePosition.Character > 0) - { - if (actualLinePosition.Character + 1 != expected.Column) - { - Assert.True(false, - string.Format("Expected diagnostic to start at column \"{0}\" was actually at column \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", - expected.Column, actualLinePosition.Character + 1, FormatDiagnostics(analyzer, diagnostic))); - } - } - } - #endregion - - #region Formatting Diagnostics - /// - /// Helper method to format a Diagnostic into an easily readable string - /// - /// The analyzer that this verifier tests - /// The Diagnostics to be formatted - /// The Diagnostics formatted as a string - private static string FormatDiagnostics(DiagnosticAnalyzer analyzer, params Diagnostic[] diagnostics) - { - var builder = new StringBuilder(); - for (int i = 0; i < diagnostics.Length; ++i) - { - builder.AppendLine("// " + diagnostics[i].ToString()); - - var analyzerType = analyzer.GetType(); - var rules = analyzer.SupportedDiagnostics; - - foreach (var rule in rules) - { - if (rule != null && rule.Id == diagnostics[i].Id) - { - var location = diagnostics[i].Location; - if (location == Location.None) - { - builder.AppendFormat("GetGlobalResult({0}.{1})", analyzerType.Name, rule.Id); - } - else - { - Assert.True(location.IsInSource, - $"Test base does not currently handle diagnostics in metadata locations. Diagnostic in metadata: {diagnostics[i]}\r\n"); - - string resultMethodName = diagnostics[i].Location.SourceTree.FilePath.EndsWith(".cs") ? "GetCSharpResultAt" : "GetBasicResultAt"; - var linePosition = diagnostics[i].Location.GetLineSpan().StartLinePosition; - - builder.AppendFormat("{0}({1}, {2}, {3}.{4})", - resultMethodName, - linePosition.Line + 1, - linePosition.Character + 1, - analyzerType.Name, - rule.Id); - } - - if (i != diagnostics.Length - 1) - { - builder.Append(','); - } - - builder.AppendLine(); - break; - } - } - } - return builder.ToString(); - } - #endregion - } -} diff --git a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.csproj b/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.csproj deleted file mode 100644 index 513c24575daa..000000000000 --- a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - - - - - - - - - - - - diff --git a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs b/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs deleted file mode 100644 index ca0535937a18..000000000000 --- a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs +++ /dev/null @@ -1,68 +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.Authorization -{ - public partial class AuthenticationState - { - public AuthenticationState(System.Security.Claims.ClaimsPrincipal user) { } - public System.Security.Claims.ClaimsPrincipal User { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public delegate void AuthenticationStateChangedHandler(System.Threading.Tasks.Task task); - public abstract partial class AuthenticationStateProvider - { - protected AuthenticationStateProvider() { } - public event Microsoft.AspNetCore.Components.Authorization.AuthenticationStateChangedHandler AuthenticationStateChanged { add { } remove { } } - public abstract System.Threading.Tasks.Task GetAuthenticationStateAsync(); - protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task task) { } - } - public sealed partial class AuthorizeRouteView : Microsoft.AspNetCore.Components.RouteView - { - public AuthorizeRouteView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - } - public partial class AuthorizeView : Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore - { - public AuthorizeView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Policy { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Roles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData() { throw null; } - } - public abstract partial class AuthorizeViewCore : Microsoft.AspNetCore.Components.ComponentBase - { - protected AuthorizeViewCore() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected abstract Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData(); - [System.Diagnostics.DebuggerStepThroughAttribute] - protected override System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } - } - public partial class CascadingAuthenticationState : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - public CascadingAuthenticationState() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { } - protected override void OnInitialized() { } - void System.IDisposable.Dispose() { } - } - public partial interface IHostEnvironmentAuthenticationStateProvider - { - void SetAuthenticationState(System.Threading.Tasks.Task authenticationStateTask); - } -} diff --git a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netstandard2.0.cs b/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netstandard2.0.cs deleted file mode 100644 index ca0535937a18..000000000000 --- a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netstandard2.0.cs +++ /dev/null @@ -1,68 +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.Authorization -{ - public partial class AuthenticationState - { - public AuthenticationState(System.Security.Claims.ClaimsPrincipal user) { } - public System.Security.Claims.ClaimsPrincipal User { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public delegate void AuthenticationStateChangedHandler(System.Threading.Tasks.Task task); - public abstract partial class AuthenticationStateProvider - { - protected AuthenticationStateProvider() { } - public event Microsoft.AspNetCore.Components.Authorization.AuthenticationStateChangedHandler AuthenticationStateChanged { add { } remove { } } - public abstract System.Threading.Tasks.Task GetAuthenticationStateAsync(); - protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task task) { } - } - public sealed partial class AuthorizeRouteView : Microsoft.AspNetCore.Components.RouteView - { - public AuthorizeRouteView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - } - public partial class AuthorizeView : Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore - { - public AuthorizeView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Policy { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Roles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData() { throw null; } - } - public abstract partial class AuthorizeViewCore : Microsoft.AspNetCore.Components.ComponentBase - { - protected AuthorizeViewCore() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected abstract Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData(); - [System.Diagnostics.DebuggerStepThroughAttribute] - protected override System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } - } - public partial class CascadingAuthenticationState : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - public CascadingAuthenticationState() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { } - protected override void OnInitialized() { } - void System.IDisposable.Dispose() { } - } - public partial interface IHostEnvironmentAuthenticationStateProvider - { - void SetAuthenticationState(System.Threading.Tasks.Task authenticationStateTask); - } -} diff --git a/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs b/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs deleted file mode 100644 index c1495fb303de..000000000000 --- a/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs +++ /dev/null @@ -1,41 +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.Concurrent; -using System.Linq; -using Microsoft.AspNetCore.Authorization; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - internal static class AttributeAuthorizeDataCache - { - private static ConcurrentDictionary _cache - = new ConcurrentDictionary(); - - public static IAuthorizeData[] GetAuthorizeDataForType(Type type) - { - IAuthorizeData[] result; - if (!_cache.TryGetValue(type, out result)) - { - result = ComputeAuthorizeDataForType(type); - _cache[type] = result; // Safe race - doesn't matter if it overwrites - } - - return result; - } - - private static IAuthorizeData[] ComputeAuthorizeDataForType(Type type) - { - // Allow Anonymous skips all authorization - var allAttributes = type.GetCustomAttributes(inherit: true); - if (allAttributes.OfType().Any()) - { - return null; - } - - var authorizeDataAttributes = allAttributes.OfType().ToArray(); - return authorizeDataAttributes.Length > 0 ? authorizeDataAttributes : null; - } - } -} diff --git a/src/Components/Authorization/src/AuthenticationState.cs b/src/Components/Authorization/src/AuthenticationState.cs deleted file mode 100644 index 6a05dce35d98..000000000000 --- a/src/Components/Authorization/src/AuthenticationState.cs +++ /dev/null @@ -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 System; -using System.Security.Claims; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// Provides information about the currently authenticated user, if any. - /// - public class AuthenticationState - { - /// - /// Constructs an instance of . - /// - /// A representing the user. - public AuthenticationState(ClaimsPrincipal user) - { - User = user ?? throw new ArgumentNullException(nameof(user)); - } - - /// - /// Gets a that describes the current user. - /// - public ClaimsPrincipal User { get; } - } -} diff --git a/src/Components/Authorization/src/AuthenticationStateProvider.cs b/src/Components/Authorization/src/AuthenticationStateProvider.cs deleted file mode 100644 index 6fc9af07c72d..000000000000 --- a/src/Components/Authorization/src/AuthenticationStateProvider.cs +++ /dev/null @@ -1,46 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// Provides information about the authentication state of the current user. - /// - public abstract class AuthenticationStateProvider - { - /// - /// Asynchronously gets an that describes the current user. - /// - /// A task that, when resolved, gives an instance that describes the current user. - public abstract Task GetAuthenticationStateAsync(); - - /// - /// An event that provides notification when the - /// has changed. For example, this event may be raised if a user logs in or out. - /// - public event AuthenticationStateChangedHandler AuthenticationStateChanged; - - /// - /// Raises the event. - /// - /// A that supplies the updated . - protected void NotifyAuthenticationStateChanged(Task task) - { - if (task == null) - { - throw new ArgumentNullException(nameof(task)); - } - - AuthenticationStateChanged?.Invoke(task); - } - } - - /// - /// A handler for the event. - /// - /// A that supplies the updated . - public delegate void AuthenticationStateChangedHandler(Task task); -} diff --git a/src/Components/Authorization/src/AuthorizeDataAdapter.cs b/src/Components/Authorization/src/AuthorizeDataAdapter.cs deleted file mode 100644 index 55d369f9af2a..000000000000 --- a/src/Components/Authorization/src/AuthorizeDataAdapter.cs +++ /dev/null @@ -1,39 +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 Microsoft.AspNetCore.Authorization; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - // This is so the AuthorizeView can avoid implementing IAuthorizeData (even privately) - internal class AuthorizeDataAdapter : IAuthorizeData - { - private readonly AuthorizeView _component; - - public AuthorizeDataAdapter(AuthorizeView component) - { - _component = component ?? throw new ArgumentNullException(nameof(component)); - } - - public string Policy - { - get => _component.Policy; - set => throw new NotSupportedException(); - } - - public string Roles - { - get => _component.Roles; - set => throw new NotSupportedException(); - } - - // AuthorizeView doesn't expose any such parameter, as it wouldn't be used anyway, - // since we already have the ClaimsPrincipal by the time AuthorizeView gets involved. - public string AuthenticationSchemes - { - get => null; - set => throw new NotSupportedException(); - } - } -} diff --git a/src/Components/Authorization/src/AuthorizeRouteView.cs b/src/Components/Authorization/src/AuthorizeRouteView.cs deleted file mode 100644 index 2d7ea76698f9..000000000000 --- a/src/Components/Authorization/src/AuthorizeRouteView.cs +++ /dev/null @@ -1,117 +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.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// Combines the behaviors of and , - /// so that it displays the page matching the specified route but only if the user - /// is authorized to see it. - /// - /// Additionally, this component supplies a cascading parameter of type , - /// which makes the user's current authentication state available to descendants. - /// - public sealed class AuthorizeRouteView : RouteView - { - // We expect applications to supply their own authorizing/not-authorized content, but - // it's better to have defaults than to make the parameters mandatory because in some - // cases they will never be used (e.g., "authorizing" in out-of-box server-side Blazor) - private static readonly RenderFragment _defaultNotAuthorizedContent - = state => builder => builder.AddContent(0, "Not authorized"); - private static readonly RenderFragment _defaultAuthorizingContent - = builder => builder.AddContent(0, "Authorizing..."); - - private readonly RenderFragment _renderAuthorizeRouteViewCoreDelegate; - private readonly RenderFragment _renderAuthorizedDelegate; - private readonly RenderFragment _renderNotAuthorizedDelegate; - private readonly RenderFragment _renderAuthorizingDelegate; - - public AuthorizeRouteView() - { - // Cache the rendering delegates so that we only construct new closure instances - // when they are actually used (e.g., we never prepare a RenderFragment bound to - // the NotAuthorized content except when you are displaying that particular state) - RenderFragment renderBaseRouteViewDelegate = builder => base.Render(builder); - _renderAuthorizedDelegate = authenticateState => renderBaseRouteViewDelegate; - _renderNotAuthorizedDelegate = authenticationState => builder => RenderNotAuthorizedInDefaultLayout(builder, authenticationState); - _renderAuthorizingDelegate = RenderAuthorizingInDefaultLayout; - _renderAuthorizeRouteViewCoreDelegate = RenderAuthorizeRouteViewCore; - } - - /// - /// The content that will be displayed if the user is not authorized. - /// - [Parameter] - public RenderFragment NotAuthorized { get; set; } - - /// - /// The content that will be displayed while asynchronous authorization is in progress. - /// - [Parameter] - public RenderFragment Authorizing { get; set; } - - [CascadingParameter] - private Task ExistingCascadedAuthenticationState { get; set; } - - /// - protected override void Render(RenderTreeBuilder builder) - { - if (ExistingCascadedAuthenticationState != null) - { - // If this component is already wrapped in a (or another - // compatible provider), then don't interfere with the cascaded authentication state. - _renderAuthorizeRouteViewCoreDelegate(builder); - } - else - { - // Otherwise, implicitly wrap the output in a - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(CascadingAuthenticationState.ChildContent), _renderAuthorizeRouteViewCoreDelegate); - builder.CloseComponent(); - } - } - - private void RenderAuthorizeRouteViewCore(RenderTreeBuilder builder) - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(AuthorizeRouteViewCore.RouteData), RouteData); - builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate); - builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate); - builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate); - builder.CloseComponent(); - } - - private void RenderContentInDefaultLayout(RenderTreeBuilder builder, RenderFragment content) - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(LayoutView.Layout), DefaultLayout); - builder.AddAttribute(2, nameof(LayoutView.ChildContent), content); - builder.CloseComponent(); - } - - private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState) - { - var content = NotAuthorized ?? _defaultNotAuthorizedContent; - RenderContentInDefaultLayout(builder, content(authenticationState)); - } - - private void RenderAuthorizingInDefaultLayout(RenderTreeBuilder builder) - { - var content = Authorizing ?? _defaultAuthorizingContent; - RenderContentInDefaultLayout(builder, content); - } - - private class AuthorizeRouteViewCore : AuthorizeViewCore - { - [Parameter] - public RouteData RouteData { get; set; } - - protected override IAuthorizeData[] GetAuthorizeData() - => AttributeAuthorizeDataCache.GetAuthorizeDataForType(RouteData.PageType); - } - } -} diff --git a/src/Components/Authorization/src/AuthorizeView.cs b/src/Components/Authorization/src/AuthorizeView.cs deleted file mode 100644 index b66a00d2a46a..000000000000 --- a/src/Components/Authorization/src/AuthorizeView.cs +++ /dev/null @@ -1,39 +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.Authorization; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// Displays differing content depending on the user's authorization status. - /// - public class AuthorizeView : AuthorizeViewCore - { - private readonly IAuthorizeData[] selfAsAuthorizeData; - - /// - /// Constructs an instance of . - /// - public AuthorizeView() - { - selfAsAuthorizeData = new[] { new AuthorizeDataAdapter(this) }; - } - - /// - /// The policy name that determines whether the content can be displayed. - /// - [Parameter] public string Policy { get; set; } - - /// - /// A comma delimited list of roles that are allowed to display the content. - /// - [Parameter] public string Roles { get; set; } - - /// - /// Gets the data used for authorization. - /// - protected override IAuthorizeData[] GetAuthorizeData() - => selfAsAuthorizeData; - } -} diff --git a/src/Components/Authorization/src/AuthorizeViewCore.cs b/src/Components/Authorization/src/AuthorizeViewCore.cs deleted file mode 100644 index b225bb19bdef..000000000000 --- a/src/Components/Authorization/src/AuthorizeViewCore.cs +++ /dev/null @@ -1,136 +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.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// A base class for components that display differing content depending on the user's authorization status. - /// - public abstract class AuthorizeViewCore : ComponentBase - { - private AuthenticationState currentAuthenticationState; - private bool isAuthorized; - - /// - /// The content that will be displayed if the user is authorized. - /// - [Parameter] public RenderFragment ChildContent { get; set; } - - /// - /// The content that will be displayed if the user is not authorized. - /// - [Parameter] public RenderFragment NotAuthorized { get; set; } - - /// - /// The content that will be displayed if the user is authorized. - /// If you specify a value for this parameter, do not also specify a value for . - /// - [Parameter] public RenderFragment Authorized { get; set; } - - /// - /// The content that will be displayed while asynchronous authorization is in progress. - /// - [Parameter] public RenderFragment Authorizing { get; set; } - - /// - /// The resource to which access is being controlled. - /// - [Parameter] public object Resource { get; set; } - - [CascadingParameter] private Task AuthenticationState { get; set; } - - [Inject] private IAuthorizationPolicyProvider AuthorizationPolicyProvider { get; set; } - - [Inject] private IAuthorizationService AuthorizationService { get; set; } - - /// - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - // We're using the same sequence number for each of the content items here - // so that we can update existing instances if they are the same shape - if (currentAuthenticationState == null) - { - builder.AddContent(0, Authorizing); - } - else if (isAuthorized) - { - var authorized = Authorized ?? ChildContent; - builder.AddContent(0, authorized?.Invoke(currentAuthenticationState)); - } - else - { - builder.AddContent(0, NotAuthorized?.Invoke(currentAuthenticationState)); - } - } - - /// - protected override async Task OnParametersSetAsync() - { - // We allow 'ChildContent' for convenience in basic cases, and 'Authorized' for symmetry - // with 'NotAuthorized' in other cases. Besides naming, they are equivalent. To avoid - // confusion, explicitly prevent the case where both are supplied. - if (ChildContent != null && Authorized != null) - { - throw new InvalidOperationException($"Do not specify both '{nameof(Authorized)}' and '{nameof(ChildContent)}'."); - } - - if (AuthenticationState == null) - { - throw new InvalidOperationException($"Authorization requires a cascading parameter of type Task<{nameof(AuthenticationState)}>. Consider using {typeof(CascadingAuthenticationState).Name} to supply this."); - } - - // First render in pending state - // If the task has already completed, this render will be skipped - currentAuthenticationState = null; - - // Then render in completed state - // Importantly, we *don't* call StateHasChanged between the following async steps, - // otherwise we'd display an incorrect UI state while waiting for IsAuthorizedAsync - currentAuthenticationState = await AuthenticationState; - isAuthorized = await IsAuthorizedAsync(currentAuthenticationState.User); - } - - /// - /// Gets the data required to apply authorization rules. - /// - protected abstract IAuthorizeData[] GetAuthorizeData(); - - private async Task IsAuthorizedAsync(ClaimsPrincipal user) - { - var authorizeData = GetAuthorizeData(); - if (authorizeData == null) - { - // No authorization applies, so no need to consult the authorization service - return true; - } - - EnsureNoAuthenticationSchemeSpecified(authorizeData); - - var policy = await AuthorizationPolicy.CombineAsync( - AuthorizationPolicyProvider, authorizeData); - var result = await AuthorizationService.AuthorizeAsync(user, Resource, policy); - return result.Succeeded; - } - - private static void EnsureNoAuthenticationSchemeSpecified(IAuthorizeData[] authorizeData) - { - // It's not meaningful to specify a nonempty scheme, since by the time Components - // authorization runs, we already have a specific ClaimsPrincipal (we're stateful). - // To avoid any confusion, ensure the developer isn't trying to specify a scheme. - for (var i = 0; i < authorizeData.Length; i++) - { - var entry = authorizeData[i]; - if (!string.IsNullOrEmpty(entry.AuthenticationSchemes)) - { - throw new NotSupportedException($"The authorization data specifies an authentication scheme with value '{entry.AuthenticationSchemes}'. Authentication schemes cannot be specified for components."); - } - } - } - } -} diff --git a/src/Components/Authorization/src/CascadingAuthenticationState.razor b/src/Components/Authorization/src/CascadingAuthenticationState.razor deleted file mode 100644 index 87506d2c6181..000000000000 --- a/src/Components/Authorization/src/CascadingAuthenticationState.razor +++ /dev/null @@ -1,36 +0,0 @@ -@implements IDisposable -@inject AuthenticationStateProvider AuthenticationStateProvider - - - -@code { - private Task _currentAuthenticationStateTask; - - /// - /// The content to which the authentication state should be provided. - /// - [Parameter] - public RenderFragment ChildContent { get; set; } - - protected override void OnInitialized() - { - AuthenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged; - - _currentAuthenticationStateTask = AuthenticationStateProvider - .GetAuthenticationStateAsync(); - } - - private void OnAuthenticationStateChanged(Task newAuthStateTask) - { - _ = InvokeAsync(() => - { - _currentAuthenticationStateTask = newAuthStateTask; - StateHasChanged(); - }); - } - - void IDisposable.Dispose() - { - AuthenticationStateProvider.AuthenticationStateChanged -= OnAuthenticationStateChanged; - } -} diff --git a/src/Components/Authorization/src/IHostEnvironmentAuthenticationStateProvider.cs b/src/Components/Authorization/src/IHostEnvironmentAuthenticationStateProvider.cs deleted file mode 100644 index fc036572a23f..000000000000 --- a/src/Components/Authorization/src/IHostEnvironmentAuthenticationStateProvider.cs +++ /dev/null @@ -1,20 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - /// - /// An interface implemented by classes that can receive authentication - /// state information from the host environment. - /// - public interface IHostEnvironmentAuthenticationStateProvider - { - /// - /// Supplies updated authentication state data to the . - /// - /// A task that resolves with the updated . - void SetAuthenticationState(Task authenticationStateTask); - } -} diff --git a/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj b/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj deleted file mode 100644 index 8f3142849aeb..000000000000 --- a/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - $(DefaultNetCoreTargetFramework) - true - Authentication and authorization support for Blazor applications. - true - true - 3.0 - - - - - - - - diff --git a/src/Components/Authorization/test/AuthorizeRouteViewTest.cs b/src/Components/Authorization/test/AuthorizeRouteViewTest.cs deleted file mode 100644 index 5a3a5683c7df..000000000000 --- a/src/Components/Authorization/test/AuthorizeRouteViewTest.cs +++ /dev/null @@ -1,356 +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.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class AuthorizeRouteViewTest - { - private readonly static IReadOnlyDictionary EmptyParametersDictionary = new Dictionary(); - private readonly TestAuthenticationStateProvider _authenticationStateProvider; - private readonly TestRenderer _renderer; - private readonly RouteView _authorizeRouteViewComponent; - private readonly int _authorizeRouteViewComponentId; - private readonly TestAuthorizationService _testAuthorizationService; - - public AuthorizeRouteViewTest() - { - _authenticationStateProvider = new TestAuthenticationStateProvider(); - _authenticationStateProvider.CurrentAuthStateTask = Task.FromResult( - new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()))); - - _testAuthorizationService = new TestAuthorizationService(); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton(_authenticationStateProvider); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(_testAuthorizationService); - - _renderer = new TestRenderer(serviceCollection.BuildServiceProvider()); - _authorizeRouteViewComponent = new AuthorizeRouteView(); - _authorizeRouteViewComponentId = _renderer.AssignRootComponentId(_authorizeRouteViewComponent); - } - - [Fact] - public void WhenAuthorized_RendersPageInsideLayout() - { - // Arrange - var routeData = new RouteData(typeof(TestPageRequiringAuthorization), new Dictionary - { - { nameof(TestPageRequiringAuthorization.Message), "Hello, world!" } - }); - _testAuthorizationService.NextResult = AuthorizationResult.Success(); - - // Act - _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - })); - - // Assert: renders layout - var batch = _renderer.Batches.Single(); - var layoutDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(layoutDiff.Edits, - edit => AssertPrependText(batch, edit, "Layout starts here"), - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Component(batch.ReferenceFrames[edit.ReferenceFrameIndex]); - }, - edit => AssertPrependText(batch, edit, "Layout ends here")); - - // Assert: renders page - var pageDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(pageDiff.Edits, - edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!")); - } - - [Fact] - public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout() - { - // Arrange - var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); - _testAuthorizationService.NextResult = AuthorizationResult.Failed(); - - // Act - _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - })); - - // Assert: renders layout containing "not authorized" message - var batch = _renderer.Batches.Single(); - var layoutDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(layoutDiff.Edits, - edit => AssertPrependText(batch, edit, "Layout starts here"), - edit => AssertPrependText(batch, edit, "Not authorized"), - edit => AssertPrependText(batch, edit, "Layout ends here")); - } - - [Fact] - public void WhenNotAuthorized_RendersCustomNotAuthorizedContentInsideLayout() - { - // Arrange - var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); - _testAuthorizationService.NextResult = AuthorizationResult.Failed(); - _authenticationStateProvider.CurrentAuthStateTask = Task.FromResult(new AuthenticationState( - new ClaimsPrincipal(new TestIdentity { Name = "Bert" }))); - - // Act - RenderFragment customNotAuthorized = - state => builder => builder.AddContent(0, $"Go away, {state.User.Identity.Name}"); - _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - { nameof(AuthorizeRouteView.NotAuthorized), customNotAuthorized }, - })); - - // Assert: renders layout containing "not authorized" message - var batch = _renderer.Batches.Single(); - var layoutDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(layoutDiff.Edits, - edit => AssertPrependText(batch, edit, "Layout starts here"), - edit => AssertPrependText(batch, edit, "Go away, Bert"), - edit => AssertPrependText(batch, edit, "Layout ends here")); - } - - [Fact] - public async Task WhenAuthorizing_RendersDefaultAuthorizingContentInsideLayout() - { - // Arrange - var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); - var authStateTcs = new TaskCompletionSource(); - _authenticationStateProvider.CurrentAuthStateTask = authStateTcs.Task; - RenderFragment customNotAuthorized = - state => builder => builder.AddContent(0, $"Go away, {state.User.Identity.Name}"); - - // Act - var firstRenderTask = _renderer.RenderRootComponentAsync(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - { nameof(AuthorizeRouteView.NotAuthorized), customNotAuthorized }, - })); - - // Assert: renders layout containing "authorizing" message - Assert.False(firstRenderTask.IsCompleted); - var batch = _renderer.Batches.Single(); - var layoutDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(layoutDiff.Edits, - edit => AssertPrependText(batch, edit, "Layout starts here"), - edit => AssertPrependText(batch, edit, "Authorizing..."), - edit => AssertPrependText(batch, edit, "Layout ends here")); - - // Act 2: updates when authorization completes - authStateTcs.SetResult(new AuthenticationState( - new ClaimsPrincipal(new TestIdentity { Name = "Bert" }))); - await firstRenderTask; - - // Assert 2: Only the layout is updated - batch = _renderer.Batches.Skip(1).Single(); - var nonEmptyDiff = batch.DiffsInOrder.Where(d => d.Edits.Any()).Single(); - Assert.Equal(layoutDiff.ComponentId, nonEmptyDiff.ComponentId); - Assert.Collection(nonEmptyDiff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - AssertFrame.Text(batch.ReferenceFrames[edit.ReferenceFrameIndex], "Go away, Bert"); - }); - } - - [Fact] - public void WhenAuthorizing_RendersCustomAuthorizingContentInsideLayout() - { - // Arrange - var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); - var authStateTcs = new TaskCompletionSource(); - _authenticationStateProvider.CurrentAuthStateTask = authStateTcs.Task; - RenderFragment customAuthorizing = - builder => builder.AddContent(0, "Hold on, we're checking your papers."); - - // Act - var firstRenderTask = _renderer.RenderRootComponentAsync(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - { nameof(AuthorizeRouteView.Authorizing), customAuthorizing }, - })); - - // Assert: renders layout containing "authorizing" message - Assert.False(firstRenderTask.IsCompleted); - var batch = _renderer.Batches.Single(); - var layoutDiff = batch.GetComponentDiffs().Single(); - Assert.Collection(layoutDiff.Edits, - edit => AssertPrependText(batch, edit, "Layout starts here"), - edit => AssertPrependText(batch, edit, "Hold on, we're checking your papers."), - edit => AssertPrependText(batch, edit, "Layout ends here")); - } - - [Fact] - public void WithoutCascadedAuthenticationState_WrapsOutputInCascadingAuthenticationState() - { - // Arrange/Act - var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary); - _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData } - })); - - // Assert - var batch = _renderer.Batches.Single(); - var componentInstances = batch.ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Component) - .Select(f => f.Component); - - Assert.Collection(componentInstances, - // This is the hierarchy inside the AuthorizeRouteView, which contains its - // own CascadingAuthenticationState - component => Assert.IsType(component), - component => Assert.IsType>>(component), - component => Assert.IsAssignableFrom(component), - component => Assert.IsType(component), - component => Assert.IsType(component)); - } - - [Fact] - public void WithCascadedAuthenticationState_DoesNotWrapOutputInCascadingAuthenticationState() - { - // Arrange - var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary); - var rootComponent = new AuthorizeRouteViewWithExistingCascadedAuthenticationState( - _authenticationStateProvider.CurrentAuthStateTask, - routeData); - var rootComponentId = _renderer.AssignRootComponentId(rootComponent); - - // Act - _renderer.RenderRootComponent(rootComponentId); - - // Assert - var batch = _renderer.Batches.Single(); - var componentInstances = batch.ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Component) - .Select(f => f.Component); - - Assert.Collection(componentInstances, - // This is the externally-supplied cascading value - component => Assert.IsType>>(component), - component => Assert.IsType(component), - - // This is the hierarchy inside the AuthorizeRouteView. It doesn't contain a - // further CascadingAuthenticationState - component => Assert.IsAssignableFrom(component), - component => Assert.IsType(component), - component => Assert.IsType(component)); - } - - [Fact] - public void UpdatesOutputWhenRouteDataChanges() - { - // Arrange/Act 1: Start on some route - // Not asserting about the initial output, as that is covered by other tests - var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary); - _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData }, - { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, - })); - - // Act 2: Move to another route - var routeData2 = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); - var render2Task = _renderer.Dispatcher.InvokeAsync(() => _authorizeRouteViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(AuthorizeRouteView.RouteData), routeData2 }, - }))); - - // Assert: we retain the layout instance, and mutate its contents - Assert.True(render2Task.IsCompletedSuccessfully); - Assert.Equal(2, _renderer.Batches.Count); - var batch2 = _renderer.Batches[1]; - var diff = batch2.DiffsInOrder.Where(d => d.Edits.Any()).Single(); - Assert.Collection(diff.Edits, - edit => - { - // Inside the layout, we add the new content - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - AssertFrame.Text(batch2.ReferenceFrames[edit.ReferenceFrameIndex], "Not authorized"); - }, - edit => - { - // ... and remove the old content - Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type); - Assert.Equal(2, edit.SiblingIndex); - }); - } - - private static void AssertPrependText(CapturedBatch batch, RenderTreeEdit edit, string text) - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - ref var referenceFrame = ref batch.ReferenceFrames[edit.ReferenceFrameIndex]; - AssertFrame.Text(referenceFrame, text); - } - - class TestPageWithNoAuthorization : ComponentBase { } - - [Authorize] - class TestPageRequiringAuthorization : ComponentBase - { - [Parameter] public string Message { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, $"Hello from the page with message: {Message}"); - } - } - - class TestLayout : LayoutComponentBase - { - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "Layout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "Layout ends here"); - } - } - - class AuthorizeRouteViewWithExistingCascadedAuthenticationState : AutoRenderComponent - { - private readonly Task _authenticationState; - private readonly RouteData _routeData; - - public AuthorizeRouteViewWithExistingCascadedAuthenticationState( - Task authenticationState, - RouteData routeData) - { - _authenticationState = authenticationState; - _routeData = routeData; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenComponent>>(0); - builder.AddAttribute(1, nameof(CascadingValue.Value), _authenticationState); - builder.AddAttribute(2, nameof(CascadingValue.ChildContent), (RenderFragment)(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(AuthorizeRouteView.RouteData), _routeData); - builder.CloseComponent(); - })); - builder.CloseComponent(); - } - } - } -} diff --git a/src/Components/Authorization/test/AuthorizeViewTest.cs b/src/Components/Authorization/test/AuthorizeViewTest.cs deleted file mode 100644 index a28b8808c43a..000000000000 --- a/src/Components/Authorization/test/AuthorizeViewTest.cs +++ /dev/null @@ -1,524 +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.Diagnostics; -using System.Linq; -using System.Security.Claims; -using System.Security.Principal; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Authorization.Infrastructure; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class AuthorizeViewTest - { - // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch - // failures. - private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10); - - [Fact] - public void RendersNothingIfNotAuthorized() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - childContent: - context => builder => builder.AddContent(0, "This should not be rendered")); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - var diff = renderer.Batches.Single().GetComponentDiffs().Single(); - Assert.Empty(diff.Edits); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Null(call.user.Identity); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void RendersNotAuthorizedIfNotAuthorized() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - notAuthorized: - context => builder => builder.AddContent(0, $"You are not authorized, even though we know you are {context.User.Identity.Name}")); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - var diff = renderer.Batches.Single().GetComponentDiffs().Single(); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex], - "You are not authorized, even though we know you are Nellie"); - }); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void RendersNothingIfAuthorizedButNoChildContentOrAuthorizedProvided() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - authorizationService.NextResult = AuthorizationResult.Success(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView(); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - var diff = renderer.Batches.Single().GetComponentDiffs().Single(); - Assert.Empty(diff.Edits); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void RendersChildContentIfAuthorized() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - authorizationService.NextResult = AuthorizationResult.Success(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - childContent: context => builder => - builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}")); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - var diff = renderer.Batches.Single().GetComponentDiffs().Single(); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex], - "You are authenticated as Nellie"); - }); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void RendersAuthorizedIfAuthorized() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - authorizationService.NextResult = AuthorizationResult.Success(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - authorized: context => builder => - builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}")); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - var diff = renderer.Batches.Single().GetComponentDiffs().Single(); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - renderer.Batches.Single().ReferenceFrames[edit.ReferenceFrameIndex], - "You are authenticated as Nellie"); - }); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void RespondsToChangeInAuthorizationState() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - authorizationService.NextResult = AuthorizationResult.Success(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - childContent: context => builder => - builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}")); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Render in initial state. From other tests, we know this renders - // a single batch with the correct output. - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - var authorizeViewComponentId = renderer.Batches.Single() - .GetComponentFrames().Single().ComponentId; - authorizationService.AuthorizeCalls.Clear(); - - // Act - rootComponent.AuthenticationState = CreateAuthenticationState("Ronaldo"); - rootComponent.TriggerRender(); - - // Assert: It's only one new diff. We skip the intermediate "await" render state - // because the task was completed synchronously. - Assert.Equal(2, renderer.Batches.Count); - var batch = renderer.Batches.Last(); - var diff = batch.DiffsByComponentId[authorizeViewComponentId].Single(); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "You are authenticated as Ronaldo"); - }); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Ronaldo", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void ThrowsIfBothChildContentAndAuthorizedProvided() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView( - authorized: context => builder => { }, - childContent: context => builder => { }); - - // Act/Assert - renderer.AssignRootComponentId(rootComponent); - var ex = Assert.Throws(() => - rootComponent.TriggerRender()); - Assert.Equal("Do not specify both 'Authorized' and 'ChildContent'.", ex.Message); - } - - [Fact] - public void RendersNothingUntilAuthorizationCompleted() - { - // Arrange - var @event = new ManualResetEventSlim(); - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - renderer.OnUpdateDisplayComplete = () => { @event.Set(); }; - var rootComponent = WrapInAuthorizeView( - notAuthorized: - context => builder => builder.AddContent(0, "You are not authorized")); - var authTcs = new TaskCompletionSource(); - rootComponent.AuthenticationState = authTcs.Task; - - // Act/Assert 1: Auth pending - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - var batch1 = renderer.Batches.Single(); - var authorizeViewComponentId = batch1.GetComponentFrames().Single().ComponentId; - var diff1 = batch1.DiffsByComponentId[authorizeViewComponentId].Single(); - Assert.Empty(diff1.Edits); - - // Act/Assert 2: Auth process completes asynchronously - @event.Reset(); - authTcs.SetResult(new AuthenticationState(new ClaimsPrincipal())); - - // We need to wait here because the continuations of SetResult will be scheduled to run asynchronously. - @event.Wait(Timeout); - - Assert.Equal(2, renderer.Batches.Count); - var batch2 = renderer.Batches[1]; - var diff2 = batch2.DiffsByComponentId[authorizeViewComponentId].Single(); - Assert.Collection(diff2.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch2.ReferenceFrames[edit.ReferenceFrameIndex], - "You are not authorized"); - }); - } - - [Fact] - public void RendersAuthorizingUntilAuthorizationCompleted() - { - // Arrange - var @event = new ManualResetEventSlim(); - var authorizationService = new TestAuthorizationService(); - authorizationService.NextResult = AuthorizationResult.Success(); - var renderer = CreateTestRenderer(authorizationService); - renderer.OnUpdateDisplayComplete = () => { @event.Set(); }; - var rootComponent = WrapInAuthorizeView( - authorizing: builder => builder.AddContent(0, "Auth pending..."), - authorized: context => builder => builder.AddContent(0, $"Hello, {context.User.Identity.Name}!")); - var authTcs = new TaskCompletionSource(); - rootComponent.AuthenticationState = authTcs.Task; - - // Act/Assert 1: Auth pending - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - var batch1 = renderer.Batches.Single(); - var authorizeViewComponentId = batch1.GetComponentFrames().Single().ComponentId; - var diff1 = batch1.DiffsByComponentId[authorizeViewComponentId].Single(); - Assert.Collection(diff1.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch1.ReferenceFrames[edit.ReferenceFrameIndex], - "Auth pending..."); - }); - - // Act/Assert 2: Auth process completes asynchronously - @event.Reset(); - authTcs.SetResult(CreateAuthenticationState("Monsieur").Result); - - // We need to wait here because the continuations of SetResult will be scheduled to run asynchronously. - @event.Wait(Timeout); - - Assert.Equal(2, renderer.Batches.Count); - var batch2 = renderer.Batches[1]; - var diff2 = batch2.DiffsByComponentId[authorizeViewComponentId].Single(); - Assert.Collection(diff2.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.SiblingIndex); - AssertFrame.Text( - batch2.ReferenceFrames[edit.ReferenceFrameIndex], - "Hello, Monsieur!"); - }); - - // Assert: The IAuthorizationService was given expected criteria - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Monsieur", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.IsType(req)); - }); - } - - [Fact] - public void IncludesPolicyInAuthorizeCall() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView(policy: "MyTestPolicy"); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, - req => Assert.Equal("MyTestPolicy", ((TestPolicyRequirement)req).PolicyName)); - }); - } - - [Fact] - public void IncludesRolesInAuthorizeCall() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = WrapInAuthorizeView(roles: "SuperTestRole1, SuperTestRole2"); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Null(call.resource); - Assert.Collection(call.requirements, req => Assert.Equal( - new[] { "SuperTestRole1", "SuperTestRole2" }, - ((RolesAuthorizationRequirement)req).AllowedRoles)); - }); - } - - [Fact] - public void IncludesResourceInAuthorizeCall() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var resource = new object(); - var rootComponent = WrapInAuthorizeView(resource: resource); - rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); - - // Act - renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - - // Assert - Assert.Collection(authorizationService.AuthorizeCalls, call => - { - Assert.Equal("Nellie", call.user.Identity.Name); - Assert.Same(resource, call.resource); - Assert.Collection(call.requirements, req => - Assert.IsType(req)); - }); - } - - [Fact] - public void RejectsNonemptyScheme() - { - // Arrange - var authorizationService = new TestAuthorizationService(); - var renderer = CreateTestRenderer(authorizationService); - var rootComponent = new TestAuthStateProviderComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - renderer.AssignRootComponentId(rootComponent); - - // Act/Assert - var ex = Assert.Throws(rootComponent.TriggerRender); - Assert.Equal("The authorization data specifies an authentication scheme with value 'test scheme'. Authentication schemes cannot be specified for components.", ex.Message); - } - - private static TestAuthStateProviderComponent WrapInAuthorizeView( - RenderFragment childContent = null, - RenderFragment authorized = null, - RenderFragment notAuthorized = null, - RenderFragment authorizing = null, - string policy = null, - string roles = null, - object resource = null) - { - return new TestAuthStateProviderComponent(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(AuthorizeView.ChildContent), childContent); - builder.AddAttribute(2, nameof(AuthorizeView.Authorized), authorized); - builder.AddAttribute(3, nameof(AuthorizeView.NotAuthorized), notAuthorized); - builder.AddAttribute(4, nameof(AuthorizeView.Authorizing), authorizing); - builder.AddAttribute(5, nameof(AuthorizeView.Policy), policy); - builder.AddAttribute(6, nameof(AuthorizeView.Roles), roles); - builder.AddAttribute(7, nameof(AuthorizeView.Resource), resource); - builder.CloseComponent(); - }); - } - - class TestAuthStateProviderComponent : AutoRenderComponent - { - private readonly RenderFragment _childContent; - - public Task AuthenticationState { get; set; } - = Task.FromResult(new AuthenticationState(new ClaimsPrincipal())); - - public TestAuthStateProviderComponent(RenderFragment childContent) - { - _childContent = childContent; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenComponent>>(0); - builder.AddAttribute(1, nameof(CascadingValue>.Value), AuthenticationState); - builder.AddAttribute(2, "ChildContent", (RenderFragment)(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, "ChildContent", _childContent); - builder.CloseComponent(); - })); - builder.CloseComponent(); - } - } - - // This is useful to show that the reason why a CascadingValue refreshes is because the - // value itself changed, not just that we're re-rendering the entire tree and have to - // recurse into all descendants because we're passing ChildContent - class NeverReRenderComponent : ComponentBase - { - [Parameter] public RenderFragment ChildContent { get; set; } - - protected override bool ShouldRender() => false; - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, ChildContent); - } - } - - public static Task CreateAuthenticationState(string username) - => Task.FromResult(new AuthenticationState( - new ClaimsPrincipal(new TestIdentity { Name = username }))); - - public TestRenderer CreateTestRenderer(IAuthorizationService authorizationService) - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton(authorizationService); - serviceCollection.AddSingleton(new TestAuthorizationPolicyProvider()); - return new TestRenderer(serviceCollection.BuildServiceProvider()); - } - - public class AuthorizeViewCoreWithScheme : AuthorizeViewCore - { - protected override IAuthorizeData[] GetAuthorizeData() - => new[] { new AuthorizeAttribute { AuthenticationSchemes = "test scheme" } }; - } - } -} diff --git a/src/Components/Authorization/test/CascadingAuthenticationStateTest.cs b/src/Components/Authorization/test/CascadingAuthenticationStateTest.cs deleted file mode 100644 index ab942fe82a98..000000000000 --- a/src/Components/Authorization/test/CascadingAuthenticationStateTest.cs +++ /dev/null @@ -1,207 +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.Security.Claims; -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class CascadingAuthenticationStateTest - { - [Fact] - public void RequiresRegisteredService() - { - // Arrange - var renderer = new TestRenderer(); - var component = new AutoRenderFragmentComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - - // Act/Assert - renderer.AssignRootComponentId(component); - var ex = Assert.Throws(() => component.TriggerRender()); - Assert.Contains($"There is no registered service of type '{typeof(AuthenticationStateProvider).FullName}'.", ex.Message); - } - - [Fact] - public void SuppliesSynchronouslyAvailableAuthStateToChildContent() - { - // Arrange: Service - var services = new ServiceCollection(); - var authStateProvider = new TestAuthenticationStateProvider() - { - CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState("Bert")) - }; - services.AddSingleton(authStateProvider); - - // Arrange: Renderer and component - var renderer = new TestRenderer(services.BuildServiceProvider()); - var component = new UseCascadingAuthenticationStateComponent(); - - // Act - renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Assert - var batch = renderer.Batches.Single(); - var receiveAuthStateId = batch.GetComponentFrames().Single().ComponentId; - var receiveAuthStateDiff = batch.DiffsByComponentId[receiveAuthStateId].Single(); - Assert.Collection(receiveAuthStateDiff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Authenticated: True; Name: Bert; Pending: False; Renders: 1"); - }); - } - - [Fact] - public void SuppliesAsynchronouslyAvailableAuthStateToChildContent() - { - // Arrange: Service - var services = new ServiceCollection(); - var authStateTaskCompletionSource = new TaskCompletionSource(); - var authStateProvider = new TestAuthenticationStateProvider() - { - CurrentAuthStateTask = authStateTaskCompletionSource.Task - }; - services.AddSingleton(authStateProvider); - - // Arrange: Renderer and component - var renderer = new TestRenderer(services.BuildServiceProvider()); - var component = new UseCascadingAuthenticationStateComponent(); - - // Act 1: Initial synchronous render - renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Assert 1: Empty state - var batch1 = renderer.Batches.Single(); - var receiveAuthStateFrame = batch1.GetComponentFrames().Single(); - var receiveAuthStateId = receiveAuthStateFrame.ComponentId; - var receiveAuthStateComponent = (ReceiveAuthStateComponent)receiveAuthStateFrame.Component; - var receiveAuthStateDiff1 = batch1.DiffsByComponentId[receiveAuthStateId].Single(); - Assert.Collection(receiveAuthStateDiff1.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch1.ReferenceFrames[edit.ReferenceFrameIndex], - "Authenticated: False; Name: ; Pending: True; Renders: 1"); - }); - - // Act/Assert 2: Auth state fetch task completes in background - // No new renders yet, because the cascading parameter itself hasn't changed - authStateTaskCompletionSource.SetResult(CreateAuthenticationState("Bert")); - Assert.Single(renderer.Batches); - - // Act/Assert 3: Refresh display - receiveAuthStateComponent.TriggerRender(); - Assert.Equal(2, renderer.Batches.Count); - var batch2 = renderer.Batches.Last(); - var receiveAuthStateDiff2 = batch2.DiffsByComponentId[receiveAuthStateId].Single(); - Assert.Collection(receiveAuthStateDiff2.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch2.ReferenceFrames[edit.ReferenceFrameIndex], - "Authenticated: True; Name: Bert; Pending: False; Renders: 2"); - }); - } - - [Fact] - public void RespondsToNotificationsFromAuthenticationStateProvider() - { - // Arrange: Service - var services = new ServiceCollection(); - var authStateProvider = new TestAuthenticationStateProvider() - { - CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState(null)) - }; - services.AddSingleton(authStateProvider); - - // Arrange: Renderer and component, initially rendered - var renderer = new TestRenderer(services.BuildServiceProvider()); - var component = new UseCascadingAuthenticationStateComponent(); - renderer.AssignRootComponentId(component); - component.TriggerRender(); - var receiveAuthStateId = renderer.Batches.Single() - .GetComponentFrames().Single().ComponentId; - - // Act 2: AuthenticationStateProvider issues notification - authStateProvider.TriggerAuthenticationStateChanged( - Task.FromResult(CreateAuthenticationState("Bert"))); - - // Assert 2: Re-renders content - Assert.Equal(2, renderer.Batches.Count); - var batch = renderer.Batches.Last(); - var receiveAuthStateDiff = batch.DiffsByComponentId[receiveAuthStateId].Single(); - Assert.Collection(receiveAuthStateDiff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Authenticated: True; Name: Bert; Pending: False; Renders: 2"); - }); - } - - class ReceiveAuthStateComponent : AutoRenderComponent - { - int numRenders; - - [CascadingParameter] Task AuthStateTask { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - numRenders++; - - if (AuthStateTask.IsCompleted) - { - var identity = AuthStateTask.Result.User.Identity; - builder.AddContent(0, $"Authenticated: {identity.IsAuthenticated}; Name: {identity.Name}; Pending: False; Renders: {numRenders}"); - } - else - { - builder.AddContent(0, $"Authenticated: False; Name: ; Pending: True; Renders: {numRenders}"); - } - } - } - - class UseCascadingAuthenticationStateComponent : AutoRenderComponent - { - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenComponent(0); - builder.AddAttribute(1, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent(0); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - } - } - - public static AuthenticationState CreateAuthenticationState(string username) - => new AuthenticationState(new ClaimsPrincipal(username == null - ? new ClaimsIdentity() - : (IIdentity)new TestIdentity { Name = username })); - - class TestIdentity : IIdentity - { - public string AuthenticationType => "Test"; - - public bool IsAuthenticated => true; - - public string Name { get; set; } - } - } -} diff --git a/src/Components/Authorization/test/Microsoft.AspNetCore.Components.Authorization.Tests.csproj b/src/Components/Authorization/test/Microsoft.AspNetCore.Components.Authorization.Tests.csproj deleted file mode 100644 index 5f7ae8f772c2..000000000000 --- a/src/Components/Authorization/test/Microsoft.AspNetCore.Components.Authorization.Tests.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - Microsoft.AspNetCore.Components.Authorization - - - - - - - - - - - - - diff --git a/src/Components/Authorization/test/TestAuthenticationStateProvider.cs b/src/Components/Authorization/test/TestAuthenticationStateProvider.cs deleted file mode 100644 index 3e8faf6a5027..000000000000 --- a/src/Components/Authorization/test/TestAuthenticationStateProvider.cs +++ /dev/null @@ -1,22 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class TestAuthenticationStateProvider : AuthenticationStateProvider - { - public Task CurrentAuthStateTask { get; set; } - - public override Task GetAuthenticationStateAsync() - { - return CurrentAuthStateTask; - } - - internal void TriggerAuthenticationStateChanged(Task authState) - { - NotifyAuthenticationStateChanged(authState); - } - } -} diff --git a/src/Components/Authorization/test/TestAuthorizationPolicyProvider.cs b/src/Components/Authorization/test/TestAuthorizationPolicyProvider.cs deleted file mode 100644 index 7935f7713859..000000000000 --- a/src/Components/Authorization/test/TestAuthorizationPolicyProvider.cs +++ /dev/null @@ -1,31 +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.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class TestAuthorizationPolicyProvider : IAuthorizationPolicyProvider - { - private readonly AuthorizationOptions options = new AuthorizationOptions(); - - public Task GetDefaultPolicyAsync() - => Task.FromResult(options.DefaultPolicy); - - public Task GetFallbackPolicyAsync() - => Task.FromResult(options.FallbackPolicy); - - public Task GetPolicyAsync(string policyName) => Task.FromResult( - new AuthorizationPolicy(new[] - { - new TestPolicyRequirement { PolicyName = policyName } - }, - new[] { $"TestScheme:{policyName}" })); - } - - public class TestPolicyRequirement : IAuthorizationRequirement - { - public string PolicyName { get; set; } - } -} diff --git a/src/Components/Authorization/test/TestAuthorizationService.cs b/src/Components/Authorization/test/TestAuthorizationService.cs deleted file mode 100644 index 42f2d4b93662..000000000000 --- a/src/Components/Authorization/test/TestAuthorizationService.cs +++ /dev/null @@ -1,34 +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.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class TestAuthorizationService : IAuthorizationService - { - public AuthorizationResult NextResult { get; set; } - = AuthorizationResult.Failed(); - - public List<(ClaimsPrincipal user, object resource, IEnumerable requirements)> AuthorizeCalls { get; } - = new List<(ClaimsPrincipal user, object resource, IEnumerable requirements)>(); - - public Task AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements) - { - AuthorizeCalls.Add((user, resource, requirements)); - - // The TestAuthorizationService doesn't actually apply any authorization requirements - // It just returns the specified NextResult, since we're not trying to test the logic - // in DefaultAuthorizationService or similar here. So it's up to tests to set a desired - // NextResult and assert that the expected criteria were passed by inspecting AuthorizeCalls. - return Task.FromResult(NextResult); - } - - public Task AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName) - => throw new NotImplementedException(); - } -} diff --git a/src/Components/Authorization/test/TestIdentity.cs b/src/Components/Authorization/test/TestIdentity.cs deleted file mode 100644 index 936c6ee0ea87..000000000000 --- a/src/Components/Authorization/test/TestIdentity.cs +++ /dev/null @@ -1,16 +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.Security.Principal; - -namespace Microsoft.AspNetCore.Components.Authorization -{ - public class TestIdentity : IIdentity - { - public string AuthenticationType => "Test"; - - public bool IsAuthenticated => true; - - public string Name { get; set; } - } -} diff --git a/src/Components/Blazor.sln b/src/Components/Blazor.sln new file mode 100644 index 000000000000..882b8eb5078e --- /dev/null +++ b/src/Components/Blazor.sln @@ -0,0 +1,484 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29728.190 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{46E744CC-D332-401F-B074-A40341F0F832}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wasm.Performance", "Wasm.Performance", "{9B360D1A-5355-4942-B77E-76A1AC67911B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.Driver", "benchmarkapps\Wasm.Performance\Driver\Wasm.Performance.Driver.csproj", "{85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{B29FB58D-FAE5-405E-9695-BCF93582BE9A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{E363191C-6C15-4C40-8698-B0AD5AA09700}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor", "Blazor\Blazor\src\Microsoft.AspNetCore.Blazor.csproj", "{8A585A38-917D-4A7E-8AFD-E860C76878FA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Tests", "Blazor\Blazor\test\Microsoft.AspNetCore.Blazor.Tests.csproj", "{75DA4341-5B7F-419C-8EED-3492013D8EB5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A82B9830-447D-4E26-BEB7-C724A3956C0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build", "Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj", "{201D53B3-2D33-40AD-813F-347A0C1998ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build.Tests", "Blazor\Build\test\Microsoft.AspNetCore.Blazor.Build.Tests.csproj", "{AB13059F-8F21-48F6-B9F3-EAF260D9CB81}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{B4ACD900-27B6-482B-B434-2C1E86E9D8BC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorhosted", "Blazor\Build\testassets\blazorhosted\blazorhosted.csproj", "{5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "classlibrarywithsatelliteassemblies", "Blazor\Build\testassets\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj", "{4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorClassLibrary", "Blazor\Build\testassets\razorclasslibrary\RazorClassLibrary.csproj", "{779749F3-8D4F-42BD-9219-37502AD68F0E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "standalone", "Blazor\Build\testassets\standalone\standalone.csproj", "{9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{A44FB7D1-78AB-41C4-B1C7-94399396EA6C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DevServer", "Blazor\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj", "{0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{F4995C96-8D4E-4B26-8FB8-614B020156C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient", "Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "{FAFE3FF2-D36D-47DA-833D-C382A902705E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient.Tests", "Blazor\Http\test\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", "{2C10DF3B-D138-414A-BB36-02E45A7B6025}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{37FA056D-A7B3-4F72-A8B9-8D3C175E831E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{FBD7C733-200E-4BED-8B31-2610C2263F72}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{7920B09F-8016-49CF-A229-E72D0CECDD17}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{BDBEDE12-74C1-466E-B8AE-49EC40F83866}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "Blazor\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{CFA20A59-F52B-47A2-BD5D-B600D9576BDA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "Blazor\testassets\MonoSanity\MonoSanity.csproj", "{C97721BB-8D89-4167-9E59-839C237BA270}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "Blazor\testassets\MonoSanityClient\MonoSanityClient.csproj", "{7F357E7B-BF33-4055-9A21-37B3507BFF90}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "Blazor\testassets\StandaloneApp\StandaloneApp.csproj", "{236FC110-FBE0-476D-ADC5-D98E23BAA1EE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{09758C93-6707-46E3-9211-470449280C2C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation", "Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "{52F0CF32-9506-4D9C-B715-52900B219BDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{C1CC2480-7925-4391-86F5-60653D864E87}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{194596E0-E6F5-4728-8A7A-A82EA0893111}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.E2ETests", "test\E2ETest\Microsoft.AspNetCore.Components.E2ETests.csproj", "{2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{10C06583-8506-42DE-863E-EAD48A1F7579}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTestApp", "test\testassets\BasicTestApp\BasicTestApp.csproj", "{376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.App", "test\testassets\ComponentsApp.App\ComponentsApp.App.csproj", "{1B633436-B999-467F-8A8F-778BB075CD35}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestContentPackage", "test\testassets\TestContentPackage\TestContentPackage.csproj", "{BC3DDF14-4961-49AB-8F19-2A23F535B0DE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components.TestServer", "test\testassets\TestServer\Components.TestServer.csproj", "{EACC194A-8C1B-424D-B8FE-330E14CAF525}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|x64.ActiveCfg = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|x64.Build.0 = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|x86.ActiveCfg = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Debug|x86.Build.0 = Debug|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|Any CPU.Build.0 = Release|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|x64.ActiveCfg = Release|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|x64.Build.0 = Release|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|x86.ActiveCfg = Release|Any CPU + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7}.Release|x86.Build.0 = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|x64.ActiveCfg = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|x64.Build.0 = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|x86.ActiveCfg = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Debug|x86.Build.0 = Debug|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|Any CPU.Build.0 = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|x64.ActiveCfg = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|x64.Build.0 = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|x86.ActiveCfg = Release|Any CPU + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}.Release|x86.Build.0 = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|x64.ActiveCfg = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|x64.Build.0 = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|x86.ActiveCfg = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Debug|x86.Build.0 = Debug|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|Any CPU.Build.0 = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|x64.ActiveCfg = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|x64.Build.0 = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|x86.ActiveCfg = Release|Any CPU + {8A585A38-917D-4A7E-8AFD-E860C76878FA}.Release|x86.Build.0 = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|x64.ActiveCfg = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|x64.Build.0 = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|x86.ActiveCfg = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Debug|x86.Build.0 = Debug|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|Any CPU.Build.0 = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|x64.ActiveCfg = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|x64.Build.0 = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|x86.ActiveCfg = Release|Any CPU + {75DA4341-5B7F-419C-8EED-3492013D8EB5}.Release|x86.Build.0 = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|x64.ActiveCfg = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|x64.Build.0 = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|x86.ActiveCfg = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Debug|x86.Build.0 = Debug|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|Any CPU.Build.0 = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|x64.ActiveCfg = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|x64.Build.0 = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|x86.ActiveCfg = Release|Any CPU + {201D53B3-2D33-40AD-813F-347A0C1998ED}.Release|x86.Build.0 = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|x64.ActiveCfg = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|x64.Build.0 = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|x86.ActiveCfg = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Debug|x86.Build.0 = Debug|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|Any CPU.Build.0 = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|x64.ActiveCfg = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|x64.Build.0 = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|x86.ActiveCfg = Release|Any CPU + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81}.Release|x86.Build.0 = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|x64.ActiveCfg = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|x64.Build.0 = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|x86.ActiveCfg = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Debug|x86.Build.0 = Debug|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|Any CPU.Build.0 = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|x64.ActiveCfg = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|x64.Build.0 = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|x86.ActiveCfg = Release|Any CPU + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}.Release|x86.Build.0 = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|x64.Build.0 = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|x86.ActiveCfg = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Debug|x86.Build.0 = Debug|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|Any CPU.Build.0 = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|x64.ActiveCfg = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|x64.Build.0 = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|x86.ActiveCfg = Release|Any CPU + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}.Release|x86.Build.0 = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|x64.ActiveCfg = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|x64.Build.0 = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Debug|x86.Build.0 = Debug|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|Any CPU.Build.0 = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|x64.ActiveCfg = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|x64.Build.0 = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|x86.ActiveCfg = Release|Any CPU + {779749F3-8D4F-42BD-9219-37502AD68F0E}.Release|x86.Build.0 = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|x64.ActiveCfg = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|x64.Build.0 = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|x86.ActiveCfg = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Debug|x86.Build.0 = Debug|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|Any CPU.Build.0 = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|x64.ActiveCfg = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|x64.Build.0 = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|x86.ActiveCfg = Release|Any CPU + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}.Release|x86.Build.0 = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|x64.ActiveCfg = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|x64.Build.0 = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|x86.ActiveCfg = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Debug|x86.Build.0 = Debug|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|Any CPU.Build.0 = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|x64.ActiveCfg = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|x64.Build.0 = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|x86.ActiveCfg = Release|Any CPU + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}.Release|x86.Build.0 = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|x64.ActiveCfg = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|x64.Build.0 = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|x86.ActiveCfg = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Debug|x86.Build.0 = Debug|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|Any CPU.Build.0 = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|x64.ActiveCfg = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|x64.Build.0 = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|x86.ActiveCfg = Release|Any CPU + {FAFE3FF2-D36D-47DA-833D-C382A902705E}.Release|x86.Build.0 = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|x64.ActiveCfg = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|x64.Build.0 = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|x86.ActiveCfg = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Debug|x86.Build.0 = Debug|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|Any CPU.Build.0 = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|x64.ActiveCfg = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|x64.Build.0 = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|x86.ActiveCfg = Release|Any CPU + {2C10DF3B-D138-414A-BB36-02E45A7B6025}.Release|x86.Build.0 = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|x64.ActiveCfg = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|x64.Build.0 = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|x86.ActiveCfg = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Debug|x86.Build.0 = Debug|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|Any CPU.Build.0 = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|x64.ActiveCfg = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|x64.Build.0 = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|x86.ActiveCfg = Release|Any CPU + {FBD7C733-200E-4BED-8B31-2610C2263F72}.Release|x86.Build.0 = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|x64.ActiveCfg = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|x64.Build.0 = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|x86.ActiveCfg = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Debug|x86.Build.0 = Debug|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|Any CPU.Build.0 = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|x64.ActiveCfg = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|x64.Build.0 = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|x86.ActiveCfg = Release|Any CPU + {BDBEDE12-74C1-466E-B8AE-49EC40F83866}.Release|x86.Build.0 = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|x64.ActiveCfg = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|x64.Build.0 = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|x86.ActiveCfg = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Debug|x86.Build.0 = Debug|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|Any CPU.Build.0 = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|x64.ActiveCfg = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|x64.Build.0 = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|x86.ActiveCfg = Release|Any CPU + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}.Release|x86.Build.0 = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|x64.ActiveCfg = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|x64.Build.0 = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|x86.ActiveCfg = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Debug|x86.Build.0 = Debug|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|Any CPU.Build.0 = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|x64.ActiveCfg = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|x64.Build.0 = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|x86.ActiveCfg = Release|Any CPU + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA}.Release|x86.Build.0 = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|x64.ActiveCfg = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|x64.Build.0 = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|x86.ActiveCfg = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Debug|x86.Build.0 = Debug|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|Any CPU.Build.0 = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|x64.ActiveCfg = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|x64.Build.0 = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|x86.ActiveCfg = Release|Any CPU + {C97721BB-8D89-4167-9E59-839C237BA270}.Release|x86.Build.0 = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|x64.ActiveCfg = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|x64.Build.0 = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|x86.ActiveCfg = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Debug|x86.Build.0 = Debug|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|Any CPU.Build.0 = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|x64.ActiveCfg = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|x64.Build.0 = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|x86.ActiveCfg = Release|Any CPU + {7F357E7B-BF33-4055-9A21-37B3507BFF90}.Release|x86.Build.0 = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|x64.Build.0 = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Debug|x86.Build.0 = Debug|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|Any CPU.Build.0 = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|x64.ActiveCfg = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|x64.Build.0 = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|x86.ActiveCfg = Release|Any CPU + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE}.Release|x86.Build.0 = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|x64.Build.0 = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Debug|x86.Build.0 = Debug|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|Any CPU.Build.0 = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|x64.ActiveCfg = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|x64.Build.0 = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|x86.ActiveCfg = Release|Any CPU + {52F0CF32-9506-4D9C-B715-52900B219BDF}.Release|x86.Build.0 = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|x64.ActiveCfg = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|x64.Build.0 = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|x86.ActiveCfg = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Debug|x86.Build.0 = Debug|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|Any CPU.Build.0 = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|x64.ActiveCfg = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|x64.Build.0 = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|x86.ActiveCfg = Release|Any CPU + {C1CC2480-7925-4391-86F5-60653D864E87}.Release|x86.Build.0 = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|x64.ActiveCfg = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|x64.Build.0 = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|x86.ActiveCfg = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Debug|x86.Build.0 = Debug|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|Any CPU.Build.0 = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|x64.ActiveCfg = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|x64.Build.0 = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|x86.ActiveCfg = Release|Any CPU + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24}.Release|x86.Build.0 = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|x64.Build.0 = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Debug|x86.Build.0 = Debug|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|Any CPU.Build.0 = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|x64.ActiveCfg = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|x64.Build.0 = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|x86.ActiveCfg = Release|Any CPU + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF}.Release|x86.Build.0 = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|x64.ActiveCfg = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|x64.Build.0 = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|x86.ActiveCfg = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Debug|x86.Build.0 = Debug|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|Any CPU.Build.0 = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|x64.ActiveCfg = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|x64.Build.0 = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|x86.ActiveCfg = Release|Any CPU + {1B633436-B999-467F-8A8F-778BB075CD35}.Release|x86.Build.0 = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|x64.ActiveCfg = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|x64.Build.0 = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|x86.ActiveCfg = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Debug|x86.Build.0 = Debug|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|Any CPU.Build.0 = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|x64.ActiveCfg = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|x64.Build.0 = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|x86.ActiveCfg = Release|Any CPU + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699}.Release|x86.Build.0 = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|x64.ActiveCfg = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|x64.Build.0 = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|x86.ActiveCfg = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Debug|x86.Build.0 = Debug|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|Any CPU.Build.0 = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|x64.ActiveCfg = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|x64.Build.0 = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|x86.ActiveCfg = Release|Any CPU + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE}.Release|x86.Build.0 = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|x64.ActiveCfg = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|x64.Build.0 = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|x86.ActiveCfg = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Debug|x86.Build.0 = Debug|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|Any CPU.Build.0 = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|x64.ActiveCfg = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|x64.Build.0 = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|x86.ActiveCfg = Release|Any CPU + {EACC194A-8C1B-424D-B8FE-330E14CAF525}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {9B360D1A-5355-4942-B77E-76A1AC67911B} = {46E744CC-D332-401F-B074-A40341F0F832} + {85E2777A-F8E0-48B8-9FC4-B60FDC7B45B7} = {9B360D1A-5355-4942-B77E-76A1AC67911B} + {10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4} = {9B360D1A-5355-4942-B77E-76A1AC67911B} + {E363191C-6C15-4C40-8698-B0AD5AA09700} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {8A585A38-917D-4A7E-8AFD-E860C76878FA} = {E363191C-6C15-4C40-8698-B0AD5AA09700} + {75DA4341-5B7F-419C-8EED-3492013D8EB5} = {E363191C-6C15-4C40-8698-B0AD5AA09700} + {A82B9830-447D-4E26-BEB7-C724A3956C0D} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {201D53B3-2D33-40AD-813F-347A0C1998ED} = {A82B9830-447D-4E26-BEB7-C724A3956C0D} + {AB13059F-8F21-48F6-B9F3-EAF260D9CB81} = {A82B9830-447D-4E26-BEB7-C724A3956C0D} + {B4ACD900-27B6-482B-B434-2C1E86E9D8BC} = {A82B9830-447D-4E26-BEB7-C724A3956C0D} + {5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC} + {4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC} + {779749F3-8D4F-42BD-9219-37502AD68F0E} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC} + {9C41BA92-FBC8-4E11-9A71-0B07906A2D6C} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC} + {A44FB7D1-78AB-41C4-B1C7-94399396EA6C} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2} = {A44FB7D1-78AB-41C4-B1C7-94399396EA6C} + {F4995C96-8D4E-4B26-8FB8-614B020156C2} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {FAFE3FF2-D36D-47DA-833D-C382A902705E} = {F4995C96-8D4E-4B26-8FB8-614B020156C2} + {2C10DF3B-D138-414A-BB36-02E45A7B6025} = {F4995C96-8D4E-4B26-8FB8-614B020156C2} + {37FA056D-A7B3-4F72-A8B9-8D3C175E831E} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {FBD7C733-200E-4BED-8B31-2610C2263F72} = {37FA056D-A7B3-4F72-A8B9-8D3C175E831E} + {7920B09F-8016-49CF-A229-E72D0CECDD17} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {BDBEDE12-74C1-466E-B8AE-49EC40F83866} = {7920B09F-8016-49CF-A229-E72D0CECDD17} + {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} + {CFA20A59-F52B-47A2-BD5D-B600D9576BDA} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} + {C97721BB-8D89-4167-9E59-839C237BA270} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} + {7F357E7B-BF33-4055-9A21-37B3507BFF90} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} + {236FC110-FBE0-476D-ADC5-D98E23BAA1EE} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD} + {09758C93-6707-46E3-9211-470449280C2C} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A} + {52F0CF32-9506-4D9C-B715-52900B219BDF} = {09758C93-6707-46E3-9211-470449280C2C} + {C1CC2480-7925-4391-86F5-60653D864E87} = {09758C93-6707-46E3-9211-470449280C2C} + {2DD2A221-255E-4A57-A2C3-B24C9BDC2E24} = {194596E0-E6F5-4728-8A7A-A82EA0893111} + {10C06583-8506-42DE-863E-EAD48A1F7579} = {194596E0-E6F5-4728-8A7A-A82EA0893111} + {376D8A5F-923C-4AF9-8627-EA0E8E54AEDF} = {10C06583-8506-42DE-863E-EAD48A1F7579} + {1B633436-B999-467F-8A8F-778BB075CD35} = {10C06583-8506-42DE-863E-EAD48A1F7579} + {DA17FB91-EF6F-4C34-A5D4-1A0F7E42D699} = {10C06583-8506-42DE-863E-EAD48A1F7579} + {BC3DDF14-4961-49AB-8F19-2A23F535B0DE} = {10C06583-8506-42DE-863E-EAD48A1F7579} + {EACC194A-8C1B-424D-B8FE-330E14CAF525} = {10C06583-8506-42DE-863E-EAD48A1F7579} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {27A36094-AA50-4FFD-ADE6-C055E391F741} + EndGlobalSection +EndGlobal diff --git a/src/Components/Blazor/Blazor.sln b/src/Components/Blazor/Blazor.sln new file mode 100644 index 000000000000..b8c2890be11d --- /dev/null +++ b/src/Components/Blazor/Blazor.sln @@ -0,0 +1,440 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{8AD7BBC4-892F-4F45-A239-622DA6C181ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor", "Blazor\ref\Microsoft.AspNetCore.Blazor.csproj", "{549D1333-970B-4C0B-80E1-E96C910A4DBD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor", "Blazor\src\Microsoft.AspNetCore.Blazor.csproj", "{53E70BA4-4B34-43A4-B6F9-9BEC482650AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Tests", "Blazor\test\Microsoft.AspNetCore.Blazor.Tests.csproj", "{0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{BE77AC33-F34A-41B4-A22F-DB45A4B8E49C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Build", "Build\src\Microsoft.AspNetCore.Blazor.Build.csproj", "{814B9486-A590-4C70-A323-3C1118DB5AA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Build.Tests", "Build\test\Microsoft.AspNetCore.Blazor.Build.Tests.csproj", "{669396CA-E180-4536-BB9D-565DF522964B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "blazorhosted", "Build\testassets\blazorhosted\blazorhosted.csproj", "{D4C040D5-598E-43DB-8341-B1E14368DBE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "classlibrarywithsatelliteassemblies", "Build\testassets\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj", "{EF440F94-84ED-43DB-8D8B-671B1F345B84}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorClassLibrary", "Build\testassets\razorclasslibrary\RazorClassLibrary.csproj", "{C5AE51C7-47CD-489C-80CD-799209DAA0E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "standalone", "Build\testassets\standalone\standalone.csproj", "{92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{0B6A1C60-596A-45A8-A71E-940F463F5C0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.DevServer", "DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj", "{DD96E545-2466-4531-8F3A-D588871A4D19}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{4FD7794A-3AB7-4455-9EA6-392CEE415588}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.HttpClient", "Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "{8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.HttpClient.Tests", "Http\test\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", "{1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{6D83D4EC-451D-40B9-BF80-475667CC5DFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{3BCD0E35-4CBA-4A14-80D8-9D695F14A384}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Server", "Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{70143EFD-F167-4D8F-A4C1-201DD00C864E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{185140F7-1F8F-430F-BC47-63C2712AC67F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Client", "testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostedInAspNet.Server", "testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{02054BB0-BBBD-45BA-8260-040126E98A8D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoSanity", "testassets\MonoSanity\MonoSanity.csproj", "{02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoSanityClient", "testassets\MonoSanityClient\MonoSanityClient.csproj", "{3605D881-E511-46E4-B80B-5BFF98DA8A9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneApp", "testassets\StandaloneApp\StandaloneApp.csproj", "{3293A32D-36DF-4A8A-99F5-E35E86B48F45}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{BD3AE379-14B5-4ABD-AF0E-023715D9726F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation", "Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "{E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{92113D6B-04C3-456C-867B-87DDF02A796A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.E2ETests", "..\test\E2ETest\Microsoft.AspNetCore.Components.E2ETests.csproj", "{86002AE6-8317-4451-A649-8E95AC5148F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicTestApp", "..\test\testassets\BasicTestApp\BasicTestApp.csproj", "{8997D5A8-097E-46F9-9B99-D9A367A1B1EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.App", "..\test\testassets\ComponentsApp.App\ComponentsApp.App.csproj", "{98F9E296-DB25-4EFB-AB0F-549602F8FC16}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentsApp.Server", "..\test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestContentPackage", "..\test\testassets\TestContentPackage\TestContentPackage.csproj", "{FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Components.TestServer", "..\test\testassets\TestServer\Components.TestServer.csproj", "{D117C434-D16D-4E38-A8B7-4663944CE167}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|x64.ActiveCfg = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|x64.Build.0 = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|x86.ActiveCfg = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Debug|x86.Build.0 = Debug|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|Any CPU.Build.0 = Release|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|x64.ActiveCfg = Release|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|x64.Build.0 = Release|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|x86.ActiveCfg = Release|Any CPU + {549D1333-970B-4C0B-80E1-E96C910A4DBD}.Release|x86.Build.0 = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|x64.ActiveCfg = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|x64.Build.0 = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Debug|x86.Build.0 = Debug|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|Any CPU.Build.0 = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|x64.ActiveCfg = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|x64.Build.0 = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|x86.ActiveCfg = Release|Any CPU + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD}.Release|x86.Build.0 = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|x64.ActiveCfg = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|x64.Build.0 = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|x86.ActiveCfg = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Debug|x86.Build.0 = Debug|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|Any CPU.Build.0 = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|x64.ActiveCfg = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|x64.Build.0 = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|x86.ActiveCfg = Release|Any CPU + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9}.Release|x86.Build.0 = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|x64.ActiveCfg = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|x64.Build.0 = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|x86.ActiveCfg = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Debug|x86.Build.0 = Debug|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|Any CPU.Build.0 = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|x64.ActiveCfg = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|x64.Build.0 = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|x86.ActiveCfg = Release|Any CPU + {814B9486-A590-4C70-A323-3C1118DB5AA2}.Release|x86.Build.0 = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|x64.ActiveCfg = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|x64.Build.0 = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|x86.ActiveCfg = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Debug|x86.Build.0 = Debug|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|Any CPU.Build.0 = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|x64.ActiveCfg = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|x64.Build.0 = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|x86.ActiveCfg = Release|Any CPU + {669396CA-E180-4536-BB9D-565DF522964B}.Release|x86.Build.0 = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|x64.ActiveCfg = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|x64.Build.0 = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|x86.ActiveCfg = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Debug|x86.Build.0 = Debug|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|Any CPU.Build.0 = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|x64.ActiveCfg = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|x64.Build.0 = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|x86.ActiveCfg = Release|Any CPU + {D4C040D5-598E-43DB-8341-B1E14368DBE2}.Release|x86.Build.0 = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|x64.ActiveCfg = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|x64.Build.0 = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|x86.ActiveCfg = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Debug|x86.Build.0 = Debug|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|Any CPU.Build.0 = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|x64.ActiveCfg = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|x64.Build.0 = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|x86.ActiveCfg = Release|Any CPU + {EF440F94-84ED-43DB-8D8B-671B1F345B84}.Release|x86.Build.0 = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|x64.ActiveCfg = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|x64.Build.0 = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|x86.ActiveCfg = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Debug|x86.Build.0 = Debug|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|Any CPU.Build.0 = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|x64.ActiveCfg = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|x64.Build.0 = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|x86.ActiveCfg = Release|Any CPU + {C5AE51C7-47CD-489C-80CD-799209DAA0E5}.Release|x86.Build.0 = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|x64.ActiveCfg = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|x64.Build.0 = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|x86.ActiveCfg = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Debug|x86.Build.0 = Debug|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|Any CPU.Build.0 = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|x64.ActiveCfg = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|x64.Build.0 = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|x86.ActiveCfg = Release|Any CPU + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54}.Release|x86.Build.0 = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|x64.ActiveCfg = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|x64.Build.0 = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|x86.ActiveCfg = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Debug|x86.Build.0 = Debug|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|Any CPU.Build.0 = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|x64.ActiveCfg = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|x64.Build.0 = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|x86.ActiveCfg = Release|Any CPU + {DD96E545-2466-4531-8F3A-D588871A4D19}.Release|x86.Build.0 = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|x64.Build.0 = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|x86.ActiveCfg = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Debug|x86.Build.0 = Debug|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|Any CPU.Build.0 = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|x64.ActiveCfg = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|x64.Build.0 = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|x86.ActiveCfg = Release|Any CPU + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7}.Release|x86.Build.0 = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|x64.ActiveCfg = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|x64.Build.0 = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|x86.ActiveCfg = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Debug|x86.Build.0 = Debug|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|Any CPU.Build.0 = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|x64.ActiveCfg = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|x64.Build.0 = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|x86.ActiveCfg = Release|Any CPU + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA}.Release|x86.Build.0 = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|x64.ActiveCfg = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|x64.Build.0 = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|x86.ActiveCfg = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Debug|x86.Build.0 = Debug|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|Any CPU.Build.0 = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|x64.ActiveCfg = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|x64.Build.0 = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|x86.ActiveCfg = Release|Any CPU + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC}.Release|x86.Build.0 = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|x64.ActiveCfg = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|x64.Build.0 = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|x86.ActiveCfg = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Debug|x86.Build.0 = Debug|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|Any CPU.Build.0 = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|x64.ActiveCfg = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|x64.Build.0 = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|x86.ActiveCfg = Release|Any CPU + {70143EFD-F167-4D8F-A4C1-201DD00C864E}.Release|x86.Build.0 = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|x64.ActiveCfg = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|x64.Build.0 = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|x86.ActiveCfg = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Debug|x86.Build.0 = Debug|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|Any CPU.Build.0 = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|x64.ActiveCfg = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|x64.Build.0 = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|x86.ActiveCfg = Release|Any CPU + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D}.Release|x86.Build.0 = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|x64.ActiveCfg = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|x64.Build.0 = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|x86.ActiveCfg = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Debug|x86.Build.0 = Debug|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|Any CPU.Build.0 = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|x64.ActiveCfg = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|x64.Build.0 = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|x86.ActiveCfg = Release|Any CPU + {02054BB0-BBBD-45BA-8260-040126E98A8D}.Release|x86.Build.0 = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|x64.ActiveCfg = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|x64.Build.0 = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|x86.ActiveCfg = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Debug|x86.Build.0 = Debug|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|Any CPU.Build.0 = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|x64.ActiveCfg = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|x64.Build.0 = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|x86.ActiveCfg = Release|Any CPU + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2}.Release|x86.Build.0 = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|x64.ActiveCfg = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|x64.Build.0 = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|x86.ActiveCfg = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Debug|x86.Build.0 = Debug|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|Any CPU.Build.0 = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|x64.ActiveCfg = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|x64.Build.0 = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|x86.ActiveCfg = Release|Any CPU + {3605D881-E511-46E4-B80B-5BFF98DA8A9C}.Release|x86.Build.0 = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|x64.ActiveCfg = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|x64.Build.0 = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|x86.ActiveCfg = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Debug|x86.Build.0 = Debug|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|Any CPU.Build.0 = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|x64.ActiveCfg = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|x64.Build.0 = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|x86.ActiveCfg = Release|Any CPU + {3293A32D-36DF-4A8A-99F5-E35E86B48F45}.Release|x86.Build.0 = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|x64.ActiveCfg = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|x64.Build.0 = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|x86.ActiveCfg = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Debug|x86.Build.0 = Debug|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|Any CPU.Build.0 = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|x64.ActiveCfg = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|x64.Build.0 = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|x86.ActiveCfg = Release|Any CPU + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971}.Release|x86.Build.0 = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|x64.ActiveCfg = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|x64.Build.0 = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|x86.ActiveCfg = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Debug|x86.Build.0 = Debug|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|Any CPU.Build.0 = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|x64.ActiveCfg = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|x64.Build.0 = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|x86.ActiveCfg = Release|Any CPU + {92113D6B-04C3-456C-867B-87DDF02A796A}.Release|x86.Build.0 = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|x64.Build.0 = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Debug|x86.Build.0 = Debug|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|Any CPU.Build.0 = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|x64.ActiveCfg = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|x64.Build.0 = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|x86.ActiveCfg = Release|Any CPU + {86002AE6-8317-4451-A649-8E95AC5148F6}.Release|x86.Build.0 = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|x64.Build.0 = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Debug|x86.Build.0 = Debug|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|Any CPU.Build.0 = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|x64.ActiveCfg = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|x64.Build.0 = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|x86.ActiveCfg = Release|Any CPU + {8997D5A8-097E-46F9-9B99-D9A367A1B1EE}.Release|x86.Build.0 = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|x64.ActiveCfg = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|x64.Build.0 = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|x86.ActiveCfg = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Debug|x86.Build.0 = Debug|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|Any CPU.Build.0 = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|x64.ActiveCfg = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|x64.Build.0 = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|x86.ActiveCfg = Release|Any CPU + {98F9E296-DB25-4EFB-AB0F-549602F8FC16}.Release|x86.Build.0 = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|x64.ActiveCfg = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|x64.Build.0 = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|x86.ActiveCfg = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Debug|x86.Build.0 = Debug|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|Any CPU.Build.0 = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|x64.ActiveCfg = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|x64.Build.0 = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|x86.ActiveCfg = Release|Any CPU + {8E9F474B-D58C-49C4-8EDB-8A9BDBA3F98A}.Release|x86.Build.0 = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|x64.ActiveCfg = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|x64.Build.0 = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|x86.ActiveCfg = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Debug|x86.Build.0 = Debug|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|Any CPU.Build.0 = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|x64.ActiveCfg = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|x64.Build.0 = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|x86.ActiveCfg = Release|Any CPU + {FB0DA201-C124-4DE6-AFCD-7996C2C05BD0}.Release|x86.Build.0 = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|x64.ActiveCfg = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|x64.Build.0 = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|x86.ActiveCfg = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Debug|x86.Build.0 = Debug|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|Any CPU.Build.0 = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|x64.ActiveCfg = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|x64.Build.0 = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|x86.ActiveCfg = Release|Any CPU + {D117C434-D16D-4E38-A8B7-4663944CE167}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {549D1333-970B-4C0B-80E1-E96C910A4DBD} = {8AD7BBC4-892F-4F45-A239-622DA6C181ED} + {53E70BA4-4B34-43A4-B6F9-9BEC482650AD} = {8AD7BBC4-892F-4F45-A239-622DA6C181ED} + {0A500F50-2CA6-4FD1-B01D-F4E1D33CCCC9} = {8AD7BBC4-892F-4F45-A239-622DA6C181ED} + {814B9486-A590-4C70-A323-3C1118DB5AA2} = {BE77AC33-F34A-41B4-A22F-DB45A4B8E49C} + {669396CA-E180-4536-BB9D-565DF522964B} = {BE77AC33-F34A-41B4-A22F-DB45A4B8E49C} + {0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2} = {BE77AC33-F34A-41B4-A22F-DB45A4B8E49C} + {D4C040D5-598E-43DB-8341-B1E14368DBE2} = {0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2} + {EF440F94-84ED-43DB-8D8B-671B1F345B84} = {0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2} + {C5AE51C7-47CD-489C-80CD-799209DAA0E5} = {0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2} + {92B77A61-B60C-4F4E-96FF-C34BEEAD2D54} = {0BD0C661-CEDD-4D64-BAC8-3947D9AD21F2} + {DD96E545-2466-4531-8F3A-D588871A4D19} = {0B6A1C60-596A-45A8-A71E-940F463F5C0D} + {8EDF0733-D5DD-4D30-8E08-05EB69DD99B7} = {4FD7794A-3AB7-4455-9EA6-392CEE415588} + {1EEEF8C8-EA17-4D84-B1CE-870153C7D5DA} = {4FD7794A-3AB7-4455-9EA6-392CEE415588} + {6E3190E9-49D7-4E40-A8C6-A29519E4A6FC} = {6D83D4EC-451D-40B9-BF80-475667CC5DFE} + {70143EFD-F167-4D8F-A4C1-201DD00C864E} = {3BCD0E35-4CBA-4A14-80D8-9D695F14A384} + {9036CD3D-6B45-4B2C-8F69-C6C4D98DCF7D} = {185140F7-1F8F-430F-BC47-63C2712AC67F} + {02054BB0-BBBD-45BA-8260-040126E98A8D} = {185140F7-1F8F-430F-BC47-63C2712AC67F} + {02EFF071-DC63-4B96-9B1C-8BCAEF22BDA2} = {185140F7-1F8F-430F-BC47-63C2712AC67F} + {3605D881-E511-46E4-B80B-5BFF98DA8A9C} = {185140F7-1F8F-430F-BC47-63C2712AC67F} + {3293A32D-36DF-4A8A-99F5-E35E86B48F45} = {185140F7-1F8F-430F-BC47-63C2712AC67F} + {E0F4A65D-F0BB-4EED-ADE8-B514E0F82971} = {BD3AE379-14B5-4ABD-AF0E-023715D9726F} + {92113D6B-04C3-456C-867B-87DDF02A796A} = {BD3AE379-14B5-4ABD-AF0E-023715D9726F} + EndGlobalSection +EndGlobal diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj index 25d2991601ec..57dee19888e2 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.csproj @@ -2,6 +2,7 @@ netstandard2.1 + $(NoWarn);BL0006 diff --git a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj index ff30d9d9c83d..a4f7e14ee9d7 100644 --- a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj @@ -4,6 +4,7 @@ netstandard2.1 Build client-side single-page applications (SPAs) with Blazor running under WebAssembly. true + $(NoWarn);BL0006 diff --git a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj index 652888d604b3..678d05098a5a 100644 --- a/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj +++ b/src/Components/Blazor/Build/test/Microsoft.AspNetCore.Blazor.Build.Tests.csproj @@ -5,6 +5,7 @@ $(DefaultItemExcludes);TestFiles\**\* + $(NoWarn);BL0006 diff --git a/src/Components/Blazor/Directory.Build.props b/src/Components/Blazor/Directory.Build.props index 8df2e791dd3b..cf13978090ef 100644 --- a/src/Components/Blazor/Directory.Build.props +++ b/src/Components/Blazor/Directory.Build.props @@ -1,10 +1,4 @@ - - - - 3.1.0 - diff --git a/src/Components/Blazor/Templates/.gitignore b/src/Components/Blazor/Templates/.gitignore deleted file mode 100644 index 6216d1eae654..000000000000 --- a/src/Components/Blazor/Templates/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# We only track the .template.config.src items in source control -# The .template.config files are generated on build -src/content/**/.template.config/ diff --git a/src/Components/Components.sln b/src/Components/Components.sln deleted file mode 100644 index c88695cf66e3..000000000000 --- a/src/Components/Components.sln +++ /dev/null @@ -1,1671 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28509.92 -MinimumVisualStudioVersion = 16.0.0.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{E059A46B-56E3-41E2-83F4-B5D180056F3B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Analyzers", "Analyzers\src\Microsoft.AspNetCore.Components.Analyzers.csproj", "{ECE91401-329E-4615-8684-8E910D2741C4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Analyzers.Tests", "Analyzers\test\Microsoft.AspNetCore.Components.Analyzers.Tests.csproj", "{F000C49D-3857-42A4-918D-DA4C08691FE2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor", "Blazor\Blazor\src\Microsoft.AspNetCore.Blazor.csproj", "{641922CD-E6F5-41E7-A085-EE07C2A7328D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Tests", "Blazor\Blazor\test\Microsoft.AspNetCore.Blazor.Tests.csproj", "{958AD6D2-174B-4B5B-BEFC-FA64B5159334}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build", "Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj", "{E8AD67A4-77D3-4B85-AE19-4711388B62B1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build.Tests", "Blazor\Build\test\Microsoft.AspNetCore.Blazor.Build.Tests.csproj", "{E38FDBB0-08C1-444E-A449-69C8A59D721B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DevServer", "Blazor\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj", "{A6C8050D-7C18-4585-ADCF-833AC1765847}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{A7ABAC29-F73F-456D-AE54-46842CFC2E10}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{FD37F740-A654-4117-BFB6-9112CE4C1D3B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "Blazor\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{C1E2C117-BE47-4E29-94B3-753262D97A5C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "Blazor\testassets\MonoSanity\MonoSanity.csproj", "{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "Blazor\testassets\MonoSanityClient\MonoSanityClient.csproj", "{1C4BF2D3-44A8-4A71-B031-15B983663CB0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "Blazor\testassets\StandaloneApp\StandaloneApp.csproj", "{C0FFB29E-4696-4875-9039-E5FA1AC5A42A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{A27FF193-195B-4474-8E6C-840B2E339373}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Web", "Web\src\Microsoft.AspNetCore.Components.Web.csproj", "{3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{3D9B9B2C-E379-41BD-83D4-2E099FBDA107}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Performance", "Components\perf\Microsoft.AspNetCore.Components.Performance.csproj", "{35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components", "Components\src\Microsoft.AspNetCore.Components.csproj", "{8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Tests", "Components\test\Microsoft.AspNetCore.Components.Tests.csproj", "{C987E45D-53AE-49EB-BD22-A15789B12F7F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{3A423375-4610-4366-B9D5-C2B29A53C50D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Server", "Server\src\Microsoft.AspNetCore.Components.Server.csproj", "{8D09F716-F010-4332-AB98-22246C0FE8AA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Server.Tests", "Server\test\Microsoft.AspNetCore.Components.Server.Tests.csproj", "{FE32E389-1868-4AA2-9E47-0FC823C25106}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E9E9CF3C-CE9B-4282-B2BB-97EFC3872798}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.E2ETests", "test\E2ETest\Microsoft.AspNetCore.Components.E2ETests.csproj", "{B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{44E0D4F3-4430-4175-B482-0D1AEE4BB699}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTestApp", "test\testassets\BasicTestApp\BasicTestApp.csproj", "{4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestContentPackage", "test\testassets\TestContentPackage\TestContentPackage.csproj", "{423CCF23-C0B4-4D21-896C-16DC98689DB5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components.TestServer", "test\testassets\TestServer\Components.TestServer.csproj", "{D6AEB328-EBC0-40B1-8936-301597883DFA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Antiforgery", "..\Antiforgery\src\Microsoft.AspNetCore.Antiforgery.csproj", "{6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions", "..\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", "{766CB6A1-0507-4367-A6CC-9C2EC6A39732}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cryptography.Internal", "..\DataProtection\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj", "{992288A5-6E70-4F2D-99A6-03439BF7A5E3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection", "..\DataProtection\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj", "{27A226BA-C94A-4E99-897D-EDFB856CCCB5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore", "..\DefaultBuilder\src\Microsoft.AspNetCore.csproj", "{443DBEC1-9620-4287-A8E7-DFE46A227BE6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.Abstractions", "..\Hosting\Abstractions\src\Microsoft.AspNetCore.Hosting.Abstractions.csproj", "{C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting", "..\Hosting\Hosting\src\Microsoft.AspNetCore.Hosting.csproj", "{3A25A675-8867-420A-8921-4B6D617EBE2F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.Server.Abstractions", "..\Hosting\Server.Abstractions\src\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj", "{B25439E1-C944-4FE1-8678-AC9E866AC4EA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Html.Abstractions", "..\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj", "{214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Abstractions", "..\Http\Authentication.Abstractions\src\Microsoft.AspNetCore.Authentication.Abstractions.csproj", "{574F245D-ED2E-4B5F-9929-8E8377412E6D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Core", "..\Http\Authentication.Core\src\Microsoft.AspNetCore.Authentication.Core.csproj", "{7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Http.Headers", "..\Http\Headers\src\Microsoft.Net.Http.Headers.csproj", "{8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Abstractions", "..\Http\Http.Abstractions\src\Microsoft.AspNetCore.Http.Abstractions.csproj", "{A9291B4E-7049-4574-AC45-8D642AD3D9B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Extensions", "..\Http\Http.Extensions\src\Microsoft.AspNetCore.Http.Extensions.csproj", "{6B847B89-DEFB-478C-B0D8-0F309602A0C5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Features", "..\Http\Http.Features\src\Microsoft.AspNetCore.Http.Features.csproj", "{3D316CA9-55C6-4D72-A408-382935555361}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http", "..\Http\Http\src\Microsoft.AspNetCore.Http.csproj", "{E0EDCB3C-C93B-4368-9289-035D7D35382B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routing.Abstractions", "..\Http\Routing.Abstractions\src\Microsoft.AspNetCore.Routing.Abstractions.csproj", "{3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routing", "..\Http\Routing\src\Microsoft.AspNetCore.Routing.csproj", "{FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebUtilities", "..\Http\WebUtilities\src\Microsoft.AspNetCore.WebUtilities.csproj", "{AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Cors", "..\Middleware\CORS\src\Microsoft.AspNetCore.Cors.csproj", "{8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.Abstractions", "..\Middleware\Diagnostics.Abstractions\src\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj", "{6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics", "..\Middleware\Diagnostics\src\Microsoft.AspNetCore.Diagnostics.csproj", "{EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HostFiltering", "..\Middleware\HostFiltering\src\Microsoft.AspNetCore.HostFiltering.csproj", "{697B279A-8BC0-49C2-A57F-667E9AD81E9A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HttpOverrides", "..\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj", "{F94690E9-258C-4C10-AC26-FA31F6EB9D35}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Localization", "..\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj", "{A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.NodeServices", "..\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj", "{71209D14-8469-40FB-B052-8308AF22A0EC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ResponseCaching.Abstractions", "..\Middleware\ResponseCaching.Abstractions\src\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj", "{86CBF0C9-76C8-4084-9758-E36731AEC1D7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ResponseCompression", "..\Middleware\ResponseCompression\src\Microsoft.AspNetCore.ResponseCompression.csproj", "{EA169B0E-3F8C-4436-82F4-56768263D256}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SpaServices.Extensions", "..\Middleware\SpaServices.Extensions\src\Microsoft.AspNetCore.SpaServices.Extensions.csproj", "{1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SpaServices", "..\Middleware\SpaServices\src\Microsoft.AspNetCore.SpaServices.csproj", "{5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.StaticFiles", "..\Middleware\StaticFiles\src\Microsoft.AspNetCore.StaticFiles.csproj", "{BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets", "..\Middleware\WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj", "{AB827016-9D0A-4443-BFF0-80CB9E947D39}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Abstractions", "..\Mvc\Mvc.Abstractions\src\Microsoft.AspNetCore.Mvc.Abstractions.csproj", "{707BB7F9-3E71-4364-8AD0-949735B5D33C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers", "..\Mvc\Mvc.Analyzers\src\Microsoft.AspNetCore.Mvc.Analyzers.csproj", "{E09006B7-2022-43CD-A0D9-127282F95A57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ApiExplorer", "..\Mvc\Mvc.ApiExplorer\src\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj", "{61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Core", "..\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj", "{1F501D4D-CEA4-445B-86C9-7215A6811368}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Cors", "..\Mvc\Mvc.Cors\src\Microsoft.AspNetCore.Mvc.Cors.csproj", "{B5037DC9-2690-42FA-8725-514E4A9EFEAD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.DataAnnotations", "..\Mvc\Mvc.DataAnnotations\src\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj", "{AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Localization", "..\Mvc\Mvc.Localization\src\Microsoft.AspNetCore.Mvc.Localization.csproj", "{D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor", "..\Mvc\Mvc.Razor\src\Microsoft.AspNetCore.Mvc.Razor.csproj", "{74F10D31-161F-49A4-ACD7-282211447CE4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.RazorPages", "..\Mvc\Mvc.RazorPages\src\Microsoft.AspNetCore.Mvc.RazorPages.csproj", "{DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TagHelpers", "..\Mvc\Mvc.TagHelpers\src\Microsoft.AspNetCore.Mvc.TagHelpers.csproj", "{2BBA2091-C991-4696-B70F-5C2D114D5674}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ViewFeatures", "..\Mvc\Mvc.ViewFeatures\src\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj", "{D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc", "..\Mvc\Mvc\src\Microsoft.AspNetCore.Mvc.csproj", "{DA1687B8-10E4-4F50-B074-60D20912A9BD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Runtime", "..\Razor\Razor.Runtime\src\Microsoft.AspNetCore.Razor.Runtime.csproj", "{97CE175F-9290-479F-A6EB-EEF4C6816624}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor", "..\Razor\Razor\src\Microsoft.AspNetCore.Razor.csproj", "{492ADBEC-D788-4039-A544-E1510D9328C1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization", "..\Security\Authorization\Core\src\Microsoft.AspNetCore.Authorization.csproj", "{B0A51484-8A24-4B9C-996B-415EB7733D56}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization.Policy", "..\Security\Authorization\Policy\src\Microsoft.AspNetCore.Authorization.Policy.csproj", "{D809A2F0-0B7B-4B5D-B70C-05EFD3203301}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Connections.Abstractions", "..\Servers\Connections.Abstractions\src\Microsoft.AspNetCore.Connections.Abstractions.csproj", "{365365A2-18A9-4EF8-A4CB-F096DAF078D9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IIS", "..\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj", "{92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "..\Servers\IIS\IISIntegration\src\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{D8C72607-7E3E-4124-A065-A57F23E9F2BA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Core", "..\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", "{4272499A-C424-41DF-B6B8-DF3C19416BE2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel", "..\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj", "{E01CD19E-B0BE-4480-8B8E-3701DE862E62}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "..\Servers\Kestrel\Transport.Sockets\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj", "{AA87CAA1-2456-4108-A02F-E16B9B8A98EE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections.Common", "..\SignalR\common\Http.Connections.Common\src\Microsoft.AspNetCore.Http.Connections.Common.csproj", "{DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections", "..\SignalR\common\Http.Connections\src\Microsoft.AspNetCore.Http.Connections.csproj", "{56DA124E-A37A-44DE-9DED-2764DDF0816C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.MessagePack", "..\SignalR\common\Protocols.MessagePack\src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj", "{527DB7FD-B118-4E49-B68A-55AAE9BFA109}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson", "..\SignalR\common\Protocols.NewtonsoftJson\src\Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.csproj", "{BB6E57A6-5434-46D4-AA09-72DC29794506}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Common", "..\SignalR\common\SignalR.Common\src\Microsoft.AspNetCore.SignalR.Common.csproj", "{557608E1-1DF3-4A24-80EB-C557C676A9CE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Core", "..\SignalR\server\Core\src\Microsoft.AspNetCore.SignalR.Core.csproj", "{9241EDB4-8FCE-4F8E-9727-C9557C59907C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR", "..\SignalR\server\SignalR\src\Microsoft.AspNetCore.SignalR.csproj", "{3FAF725B-A628-4531-9F61-499660CD4347}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{2FC10057-7A0A-4E34-8302-879925BC0102}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.NewtonsoftJson", "..\Mvc\Mvc.NewtonsoftJson\src\Microsoft.AspNetCore.Mvc.NewtonsoftJson.csproj", "{04262990-929C-42BF-85A9-21C25FA95617}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "..\Features\JsonPatch\src\Microsoft.AspNetCore.JsonPatch.csproj", "{DC47C40A-FC38-44E4-94A4-ADE794E76309}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BB236B66-28C0-49DD-9CD4-C4673CD4E7B4}" - ProjectSection(SolutionItems) = preProject - ..\..\.editorconfig = ..\..\.editorconfig - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.Json", "..\SignalR\common\Protocols.Json\src\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj", "{ED210157-461B-45BB-9D86-B81A62792C30}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client", "..\SignalR\clients\csharp\Client\src\Microsoft.AspNetCore.SignalR.Client.csproj", "{DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client.Core", "..\SignalR\clients\csharp\Client.Core\src\Microsoft.AspNetCore.SignalR.Client.Core.csproj", "{0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections.Client", "..\SignalR\clients\csharp\Http.Connections.Client\src\Microsoft.AspNetCore.Http.Connections.Client.csproj", "{F88118E1-6F4A-4F89-B047-5FFD2889B9F0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient", "Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "{74D21785-2FAB-4266-B7C4-E311EC8EE0DF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient.Tests", "Blazor\Http\test\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", "{E4C01A3F-D3C1-4639-A6A9-930E918843DD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Web.Tests", "Web\test\Microsoft.AspNetCore.Components.Web.Tests.csproj", "{DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authorization", "Authorization", "{08791FEE-761D-40EF-B701-1D31FD1E6E53}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Authorization", "Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj", "{956F540A-3CDA-4913-9373-1A4E8A93BDD8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Authorization.Tests", "Authorization\test\Microsoft.AspNetCore.Components.Authorization.Tests.csproj", "{B13CDE69-ED22-4664-AAD7-686ED8CD5E88}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Forms", "Forms", "{B0EEB429-4C8C-42AA-8822-3058E7DBC98F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Forms", "Forms\src\Microsoft.AspNetCore.Components.Forms.csproj", "{A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Forms.Tests", "Forms\test\Microsoft.AspNetCore.Components.Forms.Tests.csproj", "{173D84A3-0F37-480F-AC0F-7E2DBBE32B28}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{46E4300C-5726-4108-B9A2-18BB94EB26ED}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HttpsPolicy", "..\Middleware\HttpsPolicy\src\Microsoft.AspNetCore.HttpsPolicy.csproj", "{4664276D-606A-4BB3-873A-9EE84FB22877}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorServerApp", "Samples\BlazorServerApp\BlazorServerApp.csproj", "{BBF37AF9-8290-4B70-8BA8-0F6017B3B620}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ignitor", "Ignitor", "{BDE2397D-C53A-4783-8B3A-1F54F48A6926}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ignitor", "Ignitor\src\Ignitor.csproj", "{CD0EF85C-4187-4515-A355-E5A0D4485F40}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ignitor.Test", "Ignitor\test\Ignitor.Test.csproj", "{F31E8118-014E-4CCE-8A48-5282F7B9BB3E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation", "Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "{B70F90C7-2696-4050-B24E-BF0308F4E059}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{A5617A9D-C71E-44DE-936C-27611EB40A02}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.Server", "test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{F2E27E1C-2E47-42C1-9AC7-36265A381717}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{CCC82E97-7B58-43E2-BBBD-23D82F926367}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wasm.Performance", "Wasm.Performance", "{F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.Driver", "benchmarkapps\Wasm.Performance\Driver\Wasm.Performance.Driver.csproj", "{CA9948CA-B3FA-4C2E-A726-5E47BAD19457}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|x64.ActiveCfg = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|x64.Build.0 = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|x86.ActiveCfg = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Debug|x86.Build.0 = Debug|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|Any CPU.Build.0 = Release|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|x64.ActiveCfg = Release|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|x64.Build.0 = Release|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|x86.ActiveCfg = Release|Any CPU - {ECE91401-329E-4615-8684-8E910D2741C4}.Release|x86.Build.0 = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|x64.ActiveCfg = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|x64.Build.0 = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|x86.ActiveCfg = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Debug|x86.Build.0 = Debug|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|Any CPU.Build.0 = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|x64.ActiveCfg = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|x64.Build.0 = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|x86.ActiveCfg = Release|Any CPU - {F000C49D-3857-42A4-918D-DA4C08691FE2}.Release|x86.Build.0 = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|x64.ActiveCfg = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|x64.Build.0 = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|x86.ActiveCfg = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Debug|x86.Build.0 = Debug|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|Any CPU.Build.0 = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|x64.ActiveCfg = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|x64.Build.0 = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|x86.ActiveCfg = Release|Any CPU - {641922CD-E6F5-41E7-A085-EE07C2A7328D}.Release|x86.Build.0 = Release|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|Any CPU.Build.0 = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|x64.ActiveCfg = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|x64.Build.0 = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|x86.ActiveCfg = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Debug|x86.Build.0 = Debug|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|Any CPU.ActiveCfg = Release|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|Any CPU.Build.0 = Release|Any CPU - {958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|x64.ActiveCfg = Release|Any CPU - {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 - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|x64.Build.0 = Debug|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|x86.ActiveCfg = Debug|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|x86.Build.0 = Debug|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|Any CPU.Build.0 = Release|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x64.ActiveCfg = Release|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x64.Build.0 = Release|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x86.ActiveCfg = Release|Any CPU - {A6C8050D-7C18-4585-ADCF-833AC1765847}.Release|x86.Build.0 = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|x64.ActiveCfg = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|x64.Build.0 = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|x86.ActiveCfg = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Debug|x86.Build.0 = Debug|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|Any CPU.Build.0 = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x64.ActiveCfg = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x64.Build.0 = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.ActiveCfg = Release|Any CPU - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.Build.0 = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x64.ActiveCfg = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x64.Build.0 = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x86.ActiveCfg = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x86.Build.0 = Debug|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|Any CPU.Build.0 = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|x64.ActiveCfg = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|x64.Build.0 = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|x86.ActiveCfg = Release|Any CPU - {FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Release|x86.Build.0 = Release|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|x64.ActiveCfg = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|x64.Build.0 = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|x86.ActiveCfg = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Debug|x86.Build.0 = Debug|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|Any CPU.Build.0 = Release|Any CPU - {C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|x64.ActiveCfg = Release|Any CPU - {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 - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|x64.Build.0 = Debug|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|x86.ActiveCfg = Debug|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|x86.Build.0 = Debug|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|Any CPU.Build.0 = Release|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|x64.ActiveCfg = Release|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|x64.Build.0 = Release|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|x86.ActiveCfg = Release|Any CPU - {C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Release|x86.Build.0 = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|x64.ActiveCfg = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|x64.Build.0 = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|x86.ActiveCfg = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Debug|x86.Build.0 = Debug|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|Any CPU.Build.0 = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|x64.ActiveCfg = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|x64.Build.0 = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|x86.ActiveCfg = Release|Any CPU - {3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E}.Release|x86.Build.0 = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|x64.ActiveCfg = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|x64.Build.0 = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|x86.ActiveCfg = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Debug|x86.Build.0 = Debug|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|Any CPU.Build.0 = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|x64.ActiveCfg = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|x64.Build.0 = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|x86.ActiveCfg = Release|Any CPU - {35A8AE1D-ED82-485E-A8E6-A357B3CB31B3}.Release|x86.Build.0 = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|x64.Build.0 = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Debug|x86.Build.0 = Debug|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|Any CPU.Build.0 = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|x64.ActiveCfg = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|x64.Build.0 = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|x86.ActiveCfg = Release|Any CPU - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD}.Release|x86.Build.0 = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|x64.ActiveCfg = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|x64.Build.0 = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|x86.ActiveCfg = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Debug|x86.Build.0 = Debug|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|Any CPU.Build.0 = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|x64.ActiveCfg = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|x64.Build.0 = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|x86.ActiveCfg = Release|Any CPU - {C987E45D-53AE-49EB-BD22-A15789B12F7F}.Release|x86.Build.0 = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|x64.Build.0 = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Debug|x86.Build.0 = Debug|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|Any CPU.Build.0 = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|x64.ActiveCfg = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|x64.Build.0 = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|x86.ActiveCfg = Release|Any CPU - {8D09F716-F010-4332-AB98-22246C0FE8AA}.Release|x86.Build.0 = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|x64.ActiveCfg = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|x64.Build.0 = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|x86.ActiveCfg = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Debug|x86.Build.0 = Debug|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|Any CPU.Build.0 = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|x64.ActiveCfg = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|x64.Build.0 = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|x86.ActiveCfg = Release|Any CPU - {FE32E389-1868-4AA2-9E47-0FC823C25106}.Release|x86.Build.0 = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|x64.ActiveCfg = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|x64.Build.0 = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|x86.ActiveCfg = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Debug|x86.Build.0 = Debug|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|Any CPU.Build.0 = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|x64.ActiveCfg = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|x64.Build.0 = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|x86.ActiveCfg = Release|Any CPU - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732}.Release|x86.Build.0 = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|x64.ActiveCfg = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|x64.Build.0 = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|x86.ActiveCfg = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Debug|x86.Build.0 = Debug|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|Any CPU.Build.0 = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|x64.ActiveCfg = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|x64.Build.0 = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|x86.ActiveCfg = Release|Any CPU - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929}.Release|x86.Build.0 = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|x64.Build.0 = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|x86.ActiveCfg = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Debug|x86.Build.0 = Debug|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|Any CPU.Build.0 = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|x64.ActiveCfg = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|x64.Build.0 = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|x86.ActiveCfg = Release|Any CPU - {423CCF23-C0B4-4D21-896C-16DC98689DB5}.Release|x86.Build.0 = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|x64.ActiveCfg = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|x64.Build.0 = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|x86.ActiveCfg = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Debug|x86.Build.0 = Debug|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|Any CPU.Build.0 = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|x64.ActiveCfg = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|x64.Build.0 = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|x86.ActiveCfg = Release|Any CPU - {D6AEB328-EBC0-40B1-8936-301597883DFA}.Release|x86.Build.0 = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|x64.ActiveCfg = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|x64.Build.0 = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|x86.ActiveCfg = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Debug|x86.Build.0 = Debug|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|Any CPU.Build.0 = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|x64.ActiveCfg = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|x64.Build.0 = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|x86.ActiveCfg = Release|Any CPU - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0}.Release|x86.Build.0 = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|Any CPU.Build.0 = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|x64.ActiveCfg = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|x64.Build.0 = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|x86.ActiveCfg = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Debug|x86.Build.0 = Debug|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|Any CPU.ActiveCfg = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|Any CPU.Build.0 = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|x64.ActiveCfg = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|x64.Build.0 = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|x86.ActiveCfg = Release|Any CPU - {766CB6A1-0507-4367-A6CC-9C2EC6A39732}.Release|x86.Build.0 = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|x64.ActiveCfg = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|x64.Build.0 = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Debug|x86.Build.0 = Debug|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|Any CPU.Build.0 = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|x64.ActiveCfg = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|x64.Build.0 = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|x86.ActiveCfg = Release|Any CPU - {992288A5-6E70-4F2D-99A6-03439BF7A5E3}.Release|x86.Build.0 = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|x64.Build.0 = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|x86.ActiveCfg = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Debug|x86.Build.0 = Debug|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|Any CPU.Build.0 = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|x64.ActiveCfg = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|x64.Build.0 = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|x86.ActiveCfg = Release|Any CPU - {27A226BA-C94A-4E99-897D-EDFB856CCCB5}.Release|x86.Build.0 = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|x64.ActiveCfg = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|x64.Build.0 = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|x86.ActiveCfg = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Debug|x86.Build.0 = Debug|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|Any CPU.Build.0 = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|x64.ActiveCfg = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|x64.Build.0 = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|x86.ActiveCfg = Release|Any CPU - {443DBEC1-9620-4287-A8E7-DFE46A227BE6}.Release|x86.Build.0 = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|x64.ActiveCfg = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|x64.Build.0 = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|x86.ActiveCfg = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Debug|x86.Build.0 = Debug|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|Any CPU.Build.0 = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|x64.ActiveCfg = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|x64.Build.0 = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|x86.ActiveCfg = Release|Any CPU - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863}.Release|x86.Build.0 = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|x64.ActiveCfg = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|x64.Build.0 = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|x86.ActiveCfg = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Debug|x86.Build.0 = Debug|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|Any CPU.Build.0 = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|x64.ActiveCfg = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|x64.Build.0 = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|x86.ActiveCfg = Release|Any CPU - {3A25A675-8867-420A-8921-4B6D617EBE2F}.Release|x86.Build.0 = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|x64.ActiveCfg = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|x64.Build.0 = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|x86.ActiveCfg = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Debug|x86.Build.0 = Debug|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|Any CPU.Build.0 = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|x64.ActiveCfg = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|x64.Build.0 = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|x86.ActiveCfg = Release|Any CPU - {B25439E1-C944-4FE1-8678-AC9E866AC4EA}.Release|x86.Build.0 = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|x64.ActiveCfg = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|x64.Build.0 = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|x86.ActiveCfg = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Debug|x86.Build.0 = Debug|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|Any CPU.Build.0 = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|x64.ActiveCfg = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|x64.Build.0 = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|x86.ActiveCfg = Release|Any CPU - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8}.Release|x86.Build.0 = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|x64.ActiveCfg = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|x64.Build.0 = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|x86.ActiveCfg = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Debug|x86.Build.0 = Debug|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|Any CPU.Build.0 = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|x64.ActiveCfg = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|x64.Build.0 = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|x86.ActiveCfg = Release|Any CPU - {574F245D-ED2E-4B5F-9929-8E8377412E6D}.Release|x86.Build.0 = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|x64.ActiveCfg = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|x64.Build.0 = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|x86.ActiveCfg = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Debug|x86.Build.0 = Debug|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|Any CPU.Build.0 = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|x64.ActiveCfg = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|x64.Build.0 = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|x86.ActiveCfg = Release|Any CPU - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4}.Release|x86.Build.0 = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|x64.ActiveCfg = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|x64.Build.0 = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Debug|x86.Build.0 = Debug|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|Any CPU.Build.0 = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|x64.ActiveCfg = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|x64.Build.0 = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|x86.ActiveCfg = Release|Any CPU - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5}.Release|x86.Build.0 = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|x64.ActiveCfg = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|x64.Build.0 = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|x86.ActiveCfg = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Debug|x86.Build.0 = Debug|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|Any CPU.Build.0 = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|x64.ActiveCfg = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|x64.Build.0 = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|x86.ActiveCfg = Release|Any CPU - {A9291B4E-7049-4574-AC45-8D642AD3D9B0}.Release|x86.Build.0 = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|x64.ActiveCfg = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|x64.Build.0 = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|x86.ActiveCfg = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Debug|x86.Build.0 = Debug|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|Any CPU.Build.0 = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|x64.ActiveCfg = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|x64.Build.0 = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|x86.ActiveCfg = Release|Any CPU - {6B847B89-DEFB-478C-B0D8-0F309602A0C5}.Release|x86.Build.0 = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|x64.ActiveCfg = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|x64.Build.0 = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|x86.ActiveCfg = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Debug|x86.Build.0 = Debug|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|Any CPU.Build.0 = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|x64.ActiveCfg = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|x64.Build.0 = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|x86.ActiveCfg = Release|Any CPU - {3D316CA9-55C6-4D72-A408-382935555361}.Release|x86.Build.0 = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|x64.ActiveCfg = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|x64.Build.0 = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|x86.ActiveCfg = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Debug|x86.Build.0 = Debug|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|Any CPU.Build.0 = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|x64.ActiveCfg = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|x64.Build.0 = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|x86.ActiveCfg = Release|Any CPU - {E0EDCB3C-C93B-4368-9289-035D7D35382B}.Release|x86.Build.0 = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|x64.ActiveCfg = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|x64.Build.0 = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|x86.ActiveCfg = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Debug|x86.Build.0 = Debug|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|Any CPU.Build.0 = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|x64.ActiveCfg = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|x64.Build.0 = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|x86.ActiveCfg = Release|Any CPU - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1}.Release|x86.Build.0 = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|x64.ActiveCfg = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|x64.Build.0 = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|x86.ActiveCfg = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Debug|x86.Build.0 = Debug|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|Any CPU.Build.0 = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|x64.ActiveCfg = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|x64.Build.0 = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|x86.ActiveCfg = Release|Any CPU - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7}.Release|x86.Build.0 = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|x64.ActiveCfg = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|x64.Build.0 = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Debug|x86.Build.0 = Debug|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|Any CPU.Build.0 = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|x64.ActiveCfg = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|x64.Build.0 = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|x86.ActiveCfg = Release|Any CPU - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7}.Release|x86.Build.0 = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|x64.ActiveCfg = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|x64.Build.0 = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|x86.ActiveCfg = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Debug|x86.Build.0 = Debug|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|Any CPU.Build.0 = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|x64.ActiveCfg = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|x64.Build.0 = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|x86.ActiveCfg = Release|Any CPU - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD}.Release|x86.Build.0 = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|x64.Build.0 = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|x86.ActiveCfg = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Debug|x86.Build.0 = Debug|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|Any CPU.Build.0 = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|x64.ActiveCfg = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|x64.Build.0 = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|x86.ActiveCfg = Release|Any CPU - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B}.Release|x86.Build.0 = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|x64.ActiveCfg = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|x64.Build.0 = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|x86.ActiveCfg = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Debug|x86.Build.0 = Debug|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|Any CPU.Build.0 = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|x64.ActiveCfg = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|x64.Build.0 = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|x86.ActiveCfg = Release|Any CPU - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1}.Release|x86.Build.0 = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|x64.ActiveCfg = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|x64.Build.0 = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|x86.ActiveCfg = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Debug|x86.Build.0 = Debug|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|Any CPU.Build.0 = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|x64.ActiveCfg = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|x64.Build.0 = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|x86.ActiveCfg = Release|Any CPU - {697B279A-8BC0-49C2-A57F-667E9AD81E9A}.Release|x86.Build.0 = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|x64.ActiveCfg = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|x64.Build.0 = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|x86.ActiveCfg = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Debug|x86.Build.0 = Debug|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|Any CPU.Build.0 = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|x64.ActiveCfg = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|x64.Build.0 = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|x86.ActiveCfg = Release|Any CPU - {F94690E9-258C-4C10-AC26-FA31F6EB9D35}.Release|x86.Build.0 = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|x64.ActiveCfg = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|x64.Build.0 = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|x86.ActiveCfg = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Debug|x86.Build.0 = Debug|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|Any CPU.Build.0 = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|x64.ActiveCfg = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|x64.Build.0 = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|x86.ActiveCfg = Release|Any CPU - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44}.Release|x86.Build.0 = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|x64.ActiveCfg = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|x64.Build.0 = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|x86.ActiveCfg = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Debug|x86.Build.0 = Debug|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|Any CPU.Build.0 = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|x64.ActiveCfg = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|x64.Build.0 = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|x86.ActiveCfg = Release|Any CPU - {71209D14-8469-40FB-B052-8308AF22A0EC}.Release|x86.Build.0 = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|x64.ActiveCfg = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|x64.Build.0 = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|x86.ActiveCfg = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Debug|x86.Build.0 = Debug|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|Any CPU.Build.0 = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|x64.ActiveCfg = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|x64.Build.0 = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|x86.ActiveCfg = Release|Any CPU - {86CBF0C9-76C8-4084-9758-E36731AEC1D7}.Release|x86.Build.0 = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|x64.ActiveCfg = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|x64.Build.0 = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|x86.ActiveCfg = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Debug|x86.Build.0 = Debug|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|Any CPU.Build.0 = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|x64.ActiveCfg = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|x64.Build.0 = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|x86.ActiveCfg = Release|Any CPU - {EA169B0E-3F8C-4436-82F4-56768263D256}.Release|x86.Build.0 = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|x64.ActiveCfg = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|x64.Build.0 = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|x86.ActiveCfg = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Debug|x86.Build.0 = Debug|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|Any CPU.Build.0 = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|x64.ActiveCfg = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|x64.Build.0 = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|x86.ActiveCfg = Release|Any CPU - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B}.Release|x86.Build.0 = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|x64.ActiveCfg = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|x64.Build.0 = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|x86.ActiveCfg = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Debug|x86.Build.0 = Debug|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|Any CPU.Build.0 = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|x64.ActiveCfg = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|x64.Build.0 = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|x86.ActiveCfg = Release|Any CPU - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1}.Release|x86.Build.0 = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|x64.ActiveCfg = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|x64.Build.0 = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|x86.ActiveCfg = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Debug|x86.Build.0 = Debug|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|Any CPU.Build.0 = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|x64.ActiveCfg = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|x64.Build.0 = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|x86.ActiveCfg = Release|Any CPU - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8}.Release|x86.Build.0 = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|x64.ActiveCfg = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|x64.Build.0 = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Debug|x86.Build.0 = Debug|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|Any CPU.Build.0 = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|x64.ActiveCfg = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|x64.Build.0 = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|x86.ActiveCfg = Release|Any CPU - {AB827016-9D0A-4443-BFF0-80CB9E947D39}.Release|x86.Build.0 = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|x64.ActiveCfg = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|x64.Build.0 = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|x86.ActiveCfg = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Debug|x86.Build.0 = Debug|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|Any CPU.Build.0 = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|x64.ActiveCfg = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|x64.Build.0 = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|x86.ActiveCfg = Release|Any CPU - {707BB7F9-3E71-4364-8AD0-949735B5D33C}.Release|x86.Build.0 = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|x64.ActiveCfg = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|x64.Build.0 = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|x86.ActiveCfg = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Debug|x86.Build.0 = Debug|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|Any CPU.Build.0 = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|x64.ActiveCfg = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|x64.Build.0 = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|x86.ActiveCfg = Release|Any CPU - {E09006B7-2022-43CD-A0D9-127282F95A57}.Release|x86.Build.0 = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|Any CPU.Build.0 = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|x64.ActiveCfg = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|x64.Build.0 = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|x86.ActiveCfg = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Debug|x86.Build.0 = Debug|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|Any CPU.ActiveCfg = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|Any CPU.Build.0 = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|x64.ActiveCfg = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|x64.Build.0 = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|x86.ActiveCfg = Release|Any CPU - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16}.Release|x86.Build.0 = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|x64.ActiveCfg = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|x64.Build.0 = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|x86.ActiveCfg = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Debug|x86.Build.0 = Debug|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|Any CPU.Build.0 = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|x64.ActiveCfg = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|x64.Build.0 = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|x86.ActiveCfg = Release|Any CPU - {1F501D4D-CEA4-445B-86C9-7215A6811368}.Release|x86.Build.0 = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|x64.ActiveCfg = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|x64.Build.0 = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|x86.ActiveCfg = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Debug|x86.Build.0 = Debug|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|Any CPU.Build.0 = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|x64.ActiveCfg = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|x64.Build.0 = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|x86.ActiveCfg = Release|Any CPU - {B5037DC9-2690-42FA-8725-514E4A9EFEAD}.Release|x86.Build.0 = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|x64.ActiveCfg = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|x64.Build.0 = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|x86.ActiveCfg = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Debug|x86.Build.0 = Debug|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|Any CPU.Build.0 = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|x64.ActiveCfg = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|x64.Build.0 = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|x86.ActiveCfg = Release|Any CPU - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5}.Release|x86.Build.0 = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|x64.ActiveCfg = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|x64.Build.0 = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|x86.ActiveCfg = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Debug|x86.Build.0 = Debug|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|Any CPU.Build.0 = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|x64.ActiveCfg = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|x64.Build.0 = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|x86.ActiveCfg = Release|Any CPU - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97}.Release|x86.Build.0 = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|x64.ActiveCfg = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|x64.Build.0 = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|x86.ActiveCfg = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Debug|x86.Build.0 = Debug|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|Any CPU.Build.0 = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|x64.ActiveCfg = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|x64.Build.0 = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|x86.ActiveCfg = Release|Any CPU - {74F10D31-161F-49A4-ACD7-282211447CE4}.Release|x86.Build.0 = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|x64.ActiveCfg = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|x64.Build.0 = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|x86.ActiveCfg = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Debug|x86.Build.0 = Debug|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|Any CPU.Build.0 = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|x64.ActiveCfg = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|x64.Build.0 = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|x86.ActiveCfg = Release|Any CPU - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792}.Release|x86.Build.0 = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|x64.ActiveCfg = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|x64.Build.0 = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|x86.ActiveCfg = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Debug|x86.Build.0 = Debug|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|Any CPU.Build.0 = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|x64.ActiveCfg = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|x64.Build.0 = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|x86.ActiveCfg = Release|Any CPU - {2BBA2091-C991-4696-B70F-5C2D114D5674}.Release|x86.Build.0 = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|x64.ActiveCfg = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|x64.Build.0 = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|x86.ActiveCfg = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Debug|x86.Build.0 = Debug|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|Any CPU.Build.0 = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|x64.ActiveCfg = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|x64.Build.0 = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|x86.ActiveCfg = Release|Any CPU - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE}.Release|x86.Build.0 = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|x64.ActiveCfg = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|x64.Build.0 = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|x86.ActiveCfg = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Debug|x86.Build.0 = Debug|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|Any CPU.Build.0 = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|x64.ActiveCfg = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|x64.Build.0 = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|x86.ActiveCfg = Release|Any CPU - {DA1687B8-10E4-4F50-B074-60D20912A9BD}.Release|x86.Build.0 = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|x64.ActiveCfg = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|x64.Build.0 = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|x86.ActiveCfg = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Debug|x86.Build.0 = Debug|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|Any CPU.Build.0 = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|x64.ActiveCfg = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|x64.Build.0 = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|x86.ActiveCfg = Release|Any CPU - {97CE175F-9290-479F-A6EB-EEF4C6816624}.Release|x86.Build.0 = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|x64.ActiveCfg = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|x64.Build.0 = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|x86.ActiveCfg = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Debug|x86.Build.0 = Debug|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|Any CPU.Build.0 = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|x64.ActiveCfg = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|x64.Build.0 = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|x86.ActiveCfg = Release|Any CPU - {492ADBEC-D788-4039-A544-E1510D9328C1}.Release|x86.Build.0 = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|x64.ActiveCfg = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|x64.Build.0 = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|x86.ActiveCfg = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Debug|x86.Build.0 = Debug|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|Any CPU.Build.0 = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|x64.ActiveCfg = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|x64.Build.0 = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|x86.ActiveCfg = Release|Any CPU - {B0A51484-8A24-4B9C-996B-415EB7733D56}.Release|x86.Build.0 = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|x64.ActiveCfg = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|x64.Build.0 = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|x86.ActiveCfg = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Debug|x86.Build.0 = Debug|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|Any CPU.Build.0 = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|x64.ActiveCfg = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|x64.Build.0 = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|x86.ActiveCfg = Release|Any CPU - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301}.Release|x86.Build.0 = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|x64.ActiveCfg = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|x64.Build.0 = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|x86.ActiveCfg = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Debug|x86.Build.0 = Debug|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|Any CPU.Build.0 = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|x64.ActiveCfg = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|x64.Build.0 = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|x86.ActiveCfg = Release|Any CPU - {365365A2-18A9-4EF8-A4CB-F096DAF078D9}.Release|x86.Build.0 = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|x64.ActiveCfg = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|x64.Build.0 = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|x86.ActiveCfg = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Debug|x86.Build.0 = Debug|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|Any CPU.Build.0 = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|x64.ActiveCfg = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|x64.Build.0 = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|x86.ActiveCfg = Release|Any CPU - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3}.Release|x86.Build.0 = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|x64.ActiveCfg = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|x64.Build.0 = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|x86.ActiveCfg = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Debug|x86.Build.0 = Debug|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|Any CPU.Build.0 = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|x64.ActiveCfg = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|x64.Build.0 = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|x86.ActiveCfg = Release|Any CPU - {D8C72607-7E3E-4124-A065-A57F23E9F2BA}.Release|x86.Build.0 = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|x64.ActiveCfg = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|x64.Build.0 = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|x86.ActiveCfg = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Debug|x86.Build.0 = Debug|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|Any CPU.Build.0 = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|x64.ActiveCfg = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|x64.Build.0 = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|x86.ActiveCfg = Release|Any CPU - {4272499A-C424-41DF-B6B8-DF3C19416BE2}.Release|x86.Build.0 = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|x64.ActiveCfg = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|x64.Build.0 = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|x86.ActiveCfg = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Debug|x86.Build.0 = Debug|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|Any CPU.Build.0 = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|x64.ActiveCfg = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|x64.Build.0 = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|x86.ActiveCfg = Release|Any CPU - {E01CD19E-B0BE-4480-8B8E-3701DE862E62}.Release|x86.Build.0 = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|x64.ActiveCfg = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|x64.Build.0 = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|x86.ActiveCfg = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Debug|x86.Build.0 = Debug|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|Any CPU.Build.0 = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|x64.ActiveCfg = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|x64.Build.0 = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|x86.ActiveCfg = Release|Any CPU - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE}.Release|x86.Build.0 = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|x64.ActiveCfg = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|x64.Build.0 = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|x86.ActiveCfg = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Debug|x86.Build.0 = Debug|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|Any CPU.Build.0 = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|x64.ActiveCfg = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|x64.Build.0 = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|x86.ActiveCfg = Release|Any CPU - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9}.Release|x86.Build.0 = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|x64.ActiveCfg = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|x64.Build.0 = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|x86.ActiveCfg = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Debug|x86.Build.0 = Debug|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|Any CPU.Build.0 = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|x64.ActiveCfg = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|x64.Build.0 = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|x86.ActiveCfg = Release|Any CPU - {56DA124E-A37A-44DE-9DED-2764DDF0816C}.Release|x86.Build.0 = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|Any CPU.Build.0 = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|x64.ActiveCfg = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|x64.Build.0 = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|x86.ActiveCfg = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Debug|x86.Build.0 = Debug|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|Any CPU.ActiveCfg = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|Any CPU.Build.0 = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|x64.ActiveCfg = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|x64.Build.0 = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|x86.ActiveCfg = Release|Any CPU - {527DB7FD-B118-4E49-B68A-55AAE9BFA109}.Release|x86.Build.0 = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|x64.ActiveCfg = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|x64.Build.0 = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|x86.ActiveCfg = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Debug|x86.Build.0 = Debug|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|Any CPU.Build.0 = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|x64.ActiveCfg = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|x64.Build.0 = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|x86.ActiveCfg = Release|Any CPU - {BB6E57A6-5434-46D4-AA09-72DC29794506}.Release|x86.Build.0 = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|x64.ActiveCfg = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|x64.Build.0 = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|x86.ActiveCfg = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Debug|x86.Build.0 = Debug|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|Any CPU.Build.0 = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|x64.ActiveCfg = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|x64.Build.0 = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|x86.ActiveCfg = Release|Any CPU - {557608E1-1DF3-4A24-80EB-C557C676A9CE}.Release|x86.Build.0 = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|x64.ActiveCfg = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|x64.Build.0 = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|x86.ActiveCfg = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Debug|x86.Build.0 = Debug|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|Any CPU.Build.0 = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|x64.ActiveCfg = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|x64.Build.0 = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|x86.ActiveCfg = Release|Any CPU - {9241EDB4-8FCE-4F8E-9727-C9557C59907C}.Release|x86.Build.0 = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|x64.ActiveCfg = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|x64.Build.0 = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|x86.ActiveCfg = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Debug|x86.Build.0 = Debug|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|Any CPU.Build.0 = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|x64.ActiveCfg = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|x64.Build.0 = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|x86.ActiveCfg = Release|Any CPU - {3FAF725B-A628-4531-9F61-499660CD4347}.Release|x86.Build.0 = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|x64.ActiveCfg = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|x64.Build.0 = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|x86.ActiveCfg = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Debug|x86.Build.0 = Debug|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|Any CPU.Build.0 = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|x64.ActiveCfg = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|x64.Build.0 = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|x86.ActiveCfg = Release|Any CPU - {04262990-929C-42BF-85A9-21C25FA95617}.Release|x86.Build.0 = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|x64.ActiveCfg = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|x64.Build.0 = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|x86.ActiveCfg = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Debug|x86.Build.0 = Debug|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|Any CPU.Build.0 = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|x64.ActiveCfg = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|x64.Build.0 = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|x86.ActiveCfg = Release|Any CPU - {DC47C40A-FC38-44E4-94A4-ADE794E76309}.Release|x86.Build.0 = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|x64.ActiveCfg = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|x64.Build.0 = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|x86.ActiveCfg = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Debug|x86.Build.0 = Debug|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|Any CPU.Build.0 = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|x64.ActiveCfg = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|x64.Build.0 = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|x86.ActiveCfg = Release|Any CPU - {ED210157-461B-45BB-9D86-B81A62792C30}.Release|x86.Build.0 = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|x64.ActiveCfg = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|x64.Build.0 = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|x86.ActiveCfg = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Debug|x86.Build.0 = Debug|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|Any CPU.Build.0 = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|x64.ActiveCfg = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|x64.Build.0 = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|x86.ActiveCfg = Release|Any CPU - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}.Release|x86.Build.0 = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|x64.ActiveCfg = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|x64.Build.0 = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|x86.ActiveCfg = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Debug|x86.Build.0 = Debug|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|Any CPU.Build.0 = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|x64.ActiveCfg = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|x64.Build.0 = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|x86.ActiveCfg = Release|Any CPU - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB}.Release|x86.Build.0 = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|x64.ActiveCfg = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|x64.Build.0 = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|x86.ActiveCfg = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Debug|x86.Build.0 = Debug|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|Any CPU.Build.0 = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|x64.ActiveCfg = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|x64.Build.0 = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|x86.ActiveCfg = Release|Any CPU - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0}.Release|x86.Build.0 = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|x64.ActiveCfg = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|x64.Build.0 = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|x86.ActiveCfg = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Debug|x86.Build.0 = Debug|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|Any CPU.Build.0 = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|x64.ActiveCfg = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|x64.Build.0 = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|x86.ActiveCfg = Release|Any CPU - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF}.Release|x86.Build.0 = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|x64.Build.0 = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Debug|x86.Build.0 = Debug|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|Any CPU.Build.0 = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|x64.ActiveCfg = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|x64.Build.0 = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|x86.ActiveCfg = Release|Any CPU - {E4C01A3F-D3C1-4639-A6A9-930E918843DD}.Release|x86.Build.0 = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|x64.ActiveCfg = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|x64.Build.0 = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|x86.ActiveCfg = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Debug|x86.Build.0 = Debug|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|Any CPU.Build.0 = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|x64.ActiveCfg = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|x64.Build.0 = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|x86.ActiveCfg = Release|Any CPU - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684}.Release|x86.Build.0 = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|x64.ActiveCfg = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|x64.Build.0 = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|x86.ActiveCfg = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Debug|x86.Build.0 = Debug|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|Any CPU.Build.0 = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|x64.ActiveCfg = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|x64.Build.0 = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|x86.ActiveCfg = Release|Any CPU - {956F540A-3CDA-4913-9373-1A4E8A93BDD8}.Release|x86.Build.0 = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|x64.ActiveCfg = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|x64.Build.0 = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|x86.ActiveCfg = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Debug|x86.Build.0 = Debug|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|Any CPU.Build.0 = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|x64.ActiveCfg = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|x64.Build.0 = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|x86.ActiveCfg = Release|Any CPU - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88}.Release|x86.Build.0 = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|x64.ActiveCfg = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|x64.Build.0 = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|x86.ActiveCfg = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Debug|x86.Build.0 = Debug|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|Any CPU.Build.0 = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|x64.ActiveCfg = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|x64.Build.0 = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|x86.ActiveCfg = Release|Any CPU - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED}.Release|x86.Build.0 = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|Any CPU.Build.0 = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|x64.ActiveCfg = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|x64.Build.0 = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|x86.ActiveCfg = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Debug|x86.Build.0 = Debug|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|Any CPU.ActiveCfg = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|Any CPU.Build.0 = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|x64.ActiveCfg = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|x64.Build.0 = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|x86.ActiveCfg = Release|Any CPU - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28}.Release|x86.Build.0 = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|x64.ActiveCfg = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|x64.Build.0 = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|x86.ActiveCfg = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Debug|x86.Build.0 = Debug|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|Any CPU.Build.0 = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|x64.ActiveCfg = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|x64.Build.0 = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|x86.ActiveCfg = Release|Any CPU - {4664276D-606A-4BB3-873A-9EE84FB22877}.Release|x86.Build.0 = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|x64.ActiveCfg = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|x64.Build.0 = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|x86.ActiveCfg = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Debug|x86.Build.0 = Debug|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|Any CPU.Build.0 = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|x64.ActiveCfg = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|x64.Build.0 = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|x86.ActiveCfg = Release|Any CPU - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620}.Release|x86.Build.0 = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|x64.ActiveCfg = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|x64.Build.0 = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|x86.ActiveCfg = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Debug|x86.Build.0 = Debug|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|Any CPU.Build.0 = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|x64.ActiveCfg = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|x64.Build.0 = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|x86.ActiveCfg = Release|Any CPU - {CD0EF85C-4187-4515-A355-E5A0D4485F40}.Release|x86.Build.0 = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|x64.ActiveCfg = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|x64.Build.0 = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|x86.ActiveCfg = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Debug|x86.Build.0 = Debug|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|Any CPU.Build.0 = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|x64.ActiveCfg = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|x64.Build.0 = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|x86.ActiveCfg = Release|Any CPU - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E}.Release|x86.Build.0 = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|x64.ActiveCfg = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|x64.Build.0 = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|x86.ActiveCfg = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Debug|x86.Build.0 = Debug|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|Any CPU.Build.0 = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|x64.ActiveCfg = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|x64.Build.0 = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|x86.ActiveCfg = Release|Any CPU - {B70F90C7-2696-4050-B24E-BF0308F4E059}.Release|x86.Build.0 = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|x64.ActiveCfg = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|x64.Build.0 = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|x86.ActiveCfg = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Debug|x86.Build.0 = Debug|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|Any CPU.Build.0 = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x64.ActiveCfg = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x64.Build.0 = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.ActiveCfg = Release|Any CPU - {A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.Build.0 = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.ActiveCfg = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.Build.0 = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.Build.0 = Debug|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.Build.0 = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.ActiveCfg = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.Build.0 = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.ActiveCfg = Release|Any CPU - {D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.Build.0 = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x64.ActiveCfg = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x64.Build.0 = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x86.ActiveCfg = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Debug|x86.Build.0 = Debug|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|Any CPU.Build.0 = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x64.ActiveCfg = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x64.Build.0 = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.ActiveCfg = Release|Any CPU - {F2E27E1C-2E47-42C1-9AC7-36265A381717}.Release|x86.Build.0 = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x64.ActiveCfg = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x64.Build.0 = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Debug|x86.Build.0 = Debug|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|Any CPU.Build.0 = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x64.ActiveCfg = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x64.Build.0 = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x86.ActiveCfg = Release|Any CPU - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457}.Release|x86.Build.0 = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x64.ActiveCfg = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x64.Build.0 = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x86.ActiveCfg = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Debug|x86.Build.0 = Debug|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|Any CPU.Build.0 = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x64.ActiveCfg = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x64.Build.0 = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x86.ActiveCfg = Release|Any CPU - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {ECE91401-329E-4615-8684-8E910D2741C4} = {E059A46B-56E3-41E2-83F4-B5D180056F3B} - {F000C49D-3857-42A4-918D-DA4C08691FE2} = {E059A46B-56E3-41E2-83F4-B5D180056F3B} - {641922CD-E6F5-41E7-A085-EE07C2A7328D} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {958AD6D2-174B-4B5B-BEFC-FA64B5159334} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {E8AD67A4-77D3-4B85-AE19-4711388B62B1} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {E38FDBB0-08C1-444E-A449-69C8A59D721B} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {A6C8050D-7C18-4585-ADCF-833AC1765847} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {A4859630-F9F7-4F5C-9FF3-6C013D7C58FA} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {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} - {8D49A92D-B4AA-4A5C-99C1-B4DCBD5491DD} = {3D9B9B2C-E379-41BD-83D4-2E099FBDA107} - {C987E45D-53AE-49EB-BD22-A15789B12F7F} = {3D9B9B2C-E379-41BD-83D4-2E099FBDA107} - {8D09F716-F010-4332-AB98-22246C0FE8AA} = {3A423375-4610-4366-B9D5-C2B29A53C50D} - {FE32E389-1868-4AA2-9E47-0FC823C25106} = {3A423375-4610-4366-B9D5-C2B29A53C50D} - {B998B96D-E3CD-440E-9BFD-8F4EDC9D6732} = {E9E9CF3C-CE9B-4282-B2BB-97EFC3872798} - {44E0D4F3-4430-4175-B482-0D1AEE4BB699} = {E9E9CF3C-CE9B-4282-B2BB-97EFC3872798} - {4C5AB32A-3C7E-4A55-96A7-1F5248CFE929} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} - {423CCF23-C0B4-4D21-896C-16DC98689DB5} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} - {D6AEB328-EBC0-40B1-8936-301597883DFA} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} - {6BA2DCAA-CB68-4AE2-BBBE-746A728D30E0} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {766CB6A1-0507-4367-A6CC-9C2EC6A39732} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {992288A5-6E70-4F2D-99A6-03439BF7A5E3} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {27A226BA-C94A-4E99-897D-EDFB856CCCB5} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {443DBEC1-9620-4287-A8E7-DFE46A227BE6} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {C3A07F30-F2EA-4A9C-8A83-8C0BC8144863} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {3A25A675-8867-420A-8921-4B6D617EBE2F} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {B25439E1-C944-4FE1-8678-AC9E866AC4EA} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {214B9F12-BF3F-430F-85BC-98C6CFFFE5F8} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {574F245D-ED2E-4B5F-9929-8E8377412E6D} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {7BE4D31D-D31F-422E-8C54-39B91A9A4DE4} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {8EF63B6F-A1D9-469B-9A50-DE1613ED47A5} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {A9291B4E-7049-4574-AC45-8D642AD3D9B0} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {6B847B89-DEFB-478C-B0D8-0F309602A0C5} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {3D316CA9-55C6-4D72-A408-382935555361} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {E0EDCB3C-C93B-4368-9289-035D7D35382B} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {3C001B2F-2A04-478C-8A7A-1D121E8A4BB1} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {FF3A5823-43F0-4C98-87C4-3C5973F3C7D7} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {AB47EF50-D7F4-47AB-A49D-FFB8874EC9F7} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {8C18A50B-EAEE-4CE0-8FFC-0957FD6B5DFD} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {6F46EE1F-5A3A-4D16-94C4-6CF7147BC75B} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {EF6E0BF5-F018-4C76-A7E8-EF52D2C7D9C1} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {697B279A-8BC0-49C2-A57F-667E9AD81E9A} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {F94690E9-258C-4C10-AC26-FA31F6EB9D35} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {A2AB7E2D-0FE2-4740-95E7-CE600CBD4F44} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {71209D14-8469-40FB-B052-8308AF22A0EC} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {86CBF0C9-76C8-4084-9758-E36731AEC1D7} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {EA169B0E-3F8C-4436-82F4-56768263D256} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {1CDF7EC6-A25A-44BC-8CD3-C9F6AD13CF0B} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {5AEEAA34-01A0-418D-A8D0-E89A5B9A0EF1} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {BBDB70EB-2C08-43E7-8D82-BEE18C8881C8} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {AB827016-9D0A-4443-BFF0-80CB9E947D39} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {707BB7F9-3E71-4364-8AD0-949735B5D33C} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {E09006B7-2022-43CD-A0D9-127282F95A57} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {61E8C8E2-1CF4-42DA-8822-AFEC7FA47F16} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {1F501D4D-CEA4-445B-86C9-7215A6811368} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {B5037DC9-2690-42FA-8725-514E4A9EFEAD} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {AC7782F2-1F03-4615-A600-A7FE0FDEC5E5} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {D5C02B69-4E7B-4628-8BDA-B622A2FB2A97} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {74F10D31-161F-49A4-ACD7-282211447CE4} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {DBA8E5FE-DE74-4E24-A9A2-0FBBCC1C2792} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {2BBA2091-C991-4696-B70F-5C2D114D5674} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {D9E125B3-8FFD-47CE-9C0E-FF5CEAF633AE} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {DA1687B8-10E4-4F50-B074-60D20912A9BD} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {97CE175F-9290-479F-A6EB-EEF4C6816624} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {492ADBEC-D788-4039-A544-E1510D9328C1} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {B0A51484-8A24-4B9C-996B-415EB7733D56} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {D809A2F0-0B7B-4B5D-B70C-05EFD3203301} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {365365A2-18A9-4EF8-A4CB-F096DAF078D9} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {92D23FF6-3C79-46CD-98ED-24DA16F8FDC3} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {D8C72607-7E3E-4124-A065-A57F23E9F2BA} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {4272499A-C424-41DF-B6B8-DF3C19416BE2} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {E01CD19E-B0BE-4480-8B8E-3701DE862E62} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {AA87CAA1-2456-4108-A02F-E16B9B8A98EE} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {DC2F67CC-79DD-4F7C-AFD1-AC0D12B331C9} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {56DA124E-A37A-44DE-9DED-2764DDF0816C} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {527DB7FD-B118-4E49-B68A-55AAE9BFA109} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {BB6E57A6-5434-46D4-AA09-72DC29794506} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {557608E1-1DF3-4A24-80EB-C557C676A9CE} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {9241EDB4-8FCE-4F8E-9727-C9557C59907C} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {3FAF725B-A628-4531-9F61-499660CD4347} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {ED210157-461B-45BB-9D86-B81A62792C30} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {DA137BD4-F7F1-4D53-855F-5EC40CEA36B0} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {F88118E1-6F4A-4F89-B047-5FFD2889B9F0} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {74D21785-2FAB-4266-B7C4-E311EC8EE0DF} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {E4C01A3F-D3C1-4639-A6A9-930E918843DD} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {DE297C91-B3E9-4C6F-B74D-0AF9EFEBF684} = {A27FF193-195B-4474-8E6C-840B2E339373} - {956F540A-3CDA-4913-9373-1A4E8A93BDD8} = {08791FEE-761D-40EF-B701-1D31FD1E6E53} - {B13CDE69-ED22-4664-AAD7-686ED8CD5E88} = {08791FEE-761D-40EF-B701-1D31FD1E6E53} - {A5C132FB-1E03-4DA9-8D05-80755ED1D0ED} = {B0EEB429-4C8C-42AA-8822-3058E7DBC98F} - {173D84A3-0F37-480F-AC0F-7E2DBBE32B28} = {B0EEB429-4C8C-42AA-8822-3058E7DBC98F} - {4664276D-606A-4BB3-873A-9EE84FB22877} = {2FC10057-7A0A-4E34-8302-879925BC0102} - {BBF37AF9-8290-4B70-8BA8-0F6017B3B620} = {46E4300C-5726-4108-B9A2-18BB94EB26ED} - {CD0EF85C-4187-4515-A355-E5A0D4485F40} = {BDE2397D-C53A-4783-8B3A-1F54F48A6926} - {F31E8118-014E-4CCE-8A48-5282F7B9BB3E} = {BDE2397D-C53A-4783-8B3A-1F54F48A6926} - {B70F90C7-2696-4050-B24E-BF0308F4E059} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} - {F2E27E1C-2E47-42C1-9AC7-36265A381717} = {44E0D4F3-4430-4175-B482-0D1AEE4BB699} - {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} = {CCC82E97-7B58-43E2-BBBD-23D82F926367} - {CA9948CA-B3FA-4C2E-A726-5E47BAD19457} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} - {97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE} - EndGlobalSection -EndGlobal diff --git a/src/Components/Components/perf/AssemblyInfo.cs b/src/Components/Components/perf/AssemblyInfo.cs deleted file mode 100644 index 59c4ce51802f..000000000000 --- a/src/Components/Components/perf/AssemblyInfo.cs +++ /dev/null @@ -1,4 +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. - -[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark] \ No newline at end of file diff --git a/src/Components/Components/perf/Microsoft.AspNetCore.Components.Performance.csproj b/src/Components/Components/perf/Microsoft.AspNetCore.Components.Performance.csproj deleted file mode 100644 index a893d64abd8e..000000000000 --- a/src/Components/Components/perf/Microsoft.AspNetCore.Components.Performance.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - Exe - true - true - - - - - - - - - diff --git a/src/Components/Components/perf/Program.cs b/src/Components/Components/perf/Program.cs deleted file mode 100644 index 8602bc9462b0..000000000000 --- a/src/Components/Components/perf/Program.cs +++ /dev/null @@ -1,47 +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.Diagnostics; -using Microsoft.AspNetCore.Components.Performance; - -namespace Microsoft.AspNetCore.BenchmarkDotNet.Runner -{ - internal partial class Program - { - static partial void BeforeMain(string[] args) - { - if (args.Length == 0 || args[0] != "--profile") - { - return; - } - - // Write code here if you want to profile something. Normally Benchmark.NET launches - // a separate process, which can be hard to profile. - // - // See: https://github.com/dotnet/BenchmarkDotNet/issues/387 - - // Example: - //Console.WriteLine("Starting..."); - //var stopwatch = Stopwatch.StartNew(); - //var benchmark = new RenderTreeDiffBuilderBenchmark(); - - //for (var i = 0; i < 100000; i++) - //{ - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - // benchmark.ComputeDiff_SingleFormField(); - //} - - //Console.WriteLine($"Done after {stopwatch.ElapsedMilliseconds}ms"); - //Environment.Exit(0); - } - } -} diff --git a/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs b/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs deleted file mode 100644 index 51d7fea9fc68..000000000000 --- a/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs +++ /dev/null @@ -1,114 +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.Threading.Tasks; -using BenchmarkDotNet.Attributes; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.Extensions.Logging.Abstractions; - -namespace Microsoft.AspNetCore.Components.Performance -{ - public class RenderTreeDiffBuilderBenchmark - { - private readonly Renderer renderer; - private readonly RenderTreeBuilder original; - private readonly RenderTreeBuilder modified; - private readonly RenderBatchBuilder builder; - - public RenderTreeDiffBuilderBenchmark() - { - builder = new RenderBatchBuilder(); - renderer = new FakeRenderer(); - - // A simple component for basic tests -- this is similar to what MVC scaffolding generates - // for bootstrap3 form fields, but modified to be more Component-like. - original = new RenderTreeBuilder(); - original.OpenElement(0, "div"); - original.AddAttribute(1, "class", "form-group"); - - original.OpenElement(2, "label"); - original.AddAttribute(3, "class", "control-label"); - original.AddAttribute(4, "for", "name"); - original.AddAttribute(5, "data-unvalidated", true); - original.AddContent(6, "Car"); - original.CloseElement(); - - original.OpenElement(7, "input"); - original.AddAttribute(8, "class", "form-control"); - original.AddAttribute(9, "type", "text"); - original.AddAttribute(10, "name", "name"); // Notice the gap in sequence numbers - original.AddAttribute(12, "value", ""); - original.CloseElement(); - - original.OpenElement(13, "span"); - original.AddAttribute(14, "class", "text-danger field-validation-valid"); - original.AddContent(15, ""); - original.CloseElement(); - - original.CloseElement(); - - // Now simulate some input - modified = new RenderTreeBuilder(); - modified.OpenElement(0, "div"); - modified.AddAttribute(1, "class", "form-group"); - - modified.OpenElement(2, "label"); - modified.AddAttribute(3, "class", "control-label"); - modified.AddAttribute(4, "for", "name"); - modified.AddAttribute(5, "data-unvalidated", false); - modified.AddContent(6, "Car"); - modified.CloseElement(); - - modified.OpenElement(7, "input"); - modified.AddAttribute(8, "class", "form-control"); - modified.AddAttribute(9, "type", "text"); - modified.AddAttribute(10, "name", "name"); - modified.AddAttribute(11, "data-validation-state", "invalid"); - modified.AddAttribute(12, "value", "Lamborghini"); - modified.CloseElement(); - - modified.OpenElement(13, "span"); - modified.AddAttribute(14, "class", "text-danger field-validation-invalid"); // changed - modified.AddContent(15, "No, you can't afford that."); - modified.CloseElement(); - - modified.CloseElement(); - } - - [Benchmark(Description = "RenderTreeDiffBuilder: Input and validation on a single form field.", Baseline = true)] - public void ComputeDiff_SingleFormField() - { - builder.ClearStateForCurrentBatch(); - var diff = RenderTreeDiffBuilder.ComputeDiff(renderer, builder, 0, original.GetFrames(), modified.GetFrames()); - GC.KeepAlive(diff); - } - - private class FakeRenderer : Renderer - { - public FakeRenderer() - : base(new TestServiceProvider(), NullLoggerFactory.Instance) - { - } - - public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); - - protected override void HandleException(Exception exception) - { - throw new NotImplementedException(); - } - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - => Task.CompletedTask; - } - - private class TestServiceProvider : IServiceProvider - { - public object GetService(Type serviceType) - { - return null; - } - } - } -} diff --git a/src/Components/Components/perf/readme.md b/src/Components/Components/perf/readme.md deleted file mode 100644 index 82e7adfab7f6..000000000000 --- a/src/Components/Components/perf/readme.md +++ /dev/null @@ -1,35 +0,0 @@ -# Benchmarks - -## Instructions - -### Run All Benchmarks - -To run all use `*` as parameter -``` -dotnet run -c Release -- * -``` - -### Interactive Mode - -To see the list of benchmarks run (and choose interactively): -``` -dotnet run -c Release -``` - -### Run Specific Benchmark - -To run a specific benchmark add it as parameter -``` -dotnet run -c Release -- -``` - - -## Troubleshooting - -The runner will create logs in the `\BenchmarkDotNet.Artifacts` directory. That should include a lot more information -than what gets printed to the console. - -## Results - -Also in the `\BenchmarkDotNet.Artifacts\results` directive you'll find some markdown-formatted tables suitable for posting -in a github comment. \ No newline at end of file diff --git a/src/Components/Components/ref/Directory.Build.props b/src/Components/Components/ref/Directory.Build.props deleted file mode 100644 index 322f33d633a5..000000000000 --- a/src/Components/Components/ref/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj deleted file mode 100644 index 8a32a89b9e93..000000000000 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - - - - - - - - - - - - - - - diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netcoreapp.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netcoreapp.cs deleted file mode 100644 index c4a48435b453..000000000000 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netcoreapp.cs +++ /dev/null @@ -1,550 +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 -{ - public static partial class BindConverter - { - public static bool FormatValue(bool value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(decimal value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(double value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(int value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(long value, System.Globalization.CultureInfo culture = null) { throw null; } - public static bool? FormatValue(bool? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset? value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime? value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(decimal? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(double? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(int? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(long? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(float? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(float value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(string value, System.Globalization.CultureInfo culture = null) { throw null; } - public static object FormatValue(T value, System.Globalization.CultureInfo culture = null) { throw null; } - public static bool TryConvertToBool(object obj, System.Globalization.CultureInfo culture, out bool value) { throw null; } - public static bool TryConvertToDateTime(object obj, System.Globalization.CultureInfo culture, out System.DateTime value) { throw null; } - public static bool TryConvertToDateTime(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTime value) { throw null; } - public static bool TryConvertToDateTimeOffset(object obj, System.Globalization.CultureInfo culture, out System.DateTimeOffset value) { throw null; } - public static bool TryConvertToDateTimeOffset(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTimeOffset value) { throw null; } - public static bool TryConvertToDecimal(object obj, System.Globalization.CultureInfo culture, out decimal value) { throw null; } - public static bool TryConvertToDouble(object obj, System.Globalization.CultureInfo culture, out double value) { throw null; } - public static bool TryConvertToFloat(object obj, System.Globalization.CultureInfo culture, out float value) { throw null; } - public static bool TryConvertToInt(object obj, System.Globalization.CultureInfo culture, out int value) { throw null; } - public static bool TryConvertToLong(object obj, System.Globalization.CultureInfo culture, out long value) { throw null; } - public static bool TryConvertToNullableBool(object obj, System.Globalization.CultureInfo culture, out bool? value) { throw null; } - public static bool TryConvertToNullableDateTime(object obj, System.Globalization.CultureInfo culture, out System.DateTime? value) { throw null; } - public static bool TryConvertToNullableDateTime(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTime? value) { throw null; } - public static bool TryConvertToNullableDateTimeOffset(object obj, System.Globalization.CultureInfo culture, out System.DateTimeOffset? value) { throw null; } - public static bool TryConvertToNullableDateTimeOffset(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTimeOffset? value) { throw null; } - public static bool TryConvertToNullableDecimal(object obj, System.Globalization.CultureInfo culture, out decimal? value) { throw null; } - public static bool TryConvertToNullableDouble(object obj, System.Globalization.CultureInfo culture, out double? value) { throw null; } - public static bool TryConvertToNullableFloat(object obj, System.Globalization.CultureInfo culture, out float? value) { throw null; } - public static bool TryConvertToNullableInt(object obj, System.Globalization.CultureInfo culture, out int? value) { throw null; } - public static bool TryConvertToNullableLong(object obj, System.Globalization.CultureInfo culture, out long? value) { throw null; } - public static bool TryConvertToString(object obj, System.Globalization.CultureInfo culture, out string value) { throw null; } - public static bool TryConvertTo(object obj, System.Globalization.CultureInfo culture, out T value) { throw null; } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] - public sealed partial class BindElementAttribute : System.Attribute - { - public BindElementAttribute(string element, string suffix, string valueAttribute, string changeAttribute) { } - public string ChangeAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Element { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Suffix { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class CascadingParameterAttribute : System.Attribute - { - public CascadingParameterAttribute() { } - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class CascadingValue : Microsoft.AspNetCore.Components.IComponent - { - public CascadingValue() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public bool IsFixed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } - public partial class ChangeEventArgs : System.EventArgs - { - public ChangeEventArgs() { } - public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public abstract partial class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent - { - public ComponentBase() { } - protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected System.Threading.Tasks.Task InvokeAsync(System.Action workItem) { throw null; } - protected System.Threading.Tasks.Task InvokeAsync(System.Func workItem) { throw null; } - void Microsoft.AspNetCore.Components.IComponent.Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() { throw null; } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem callback, object arg) { throw null; } - protected virtual void OnAfterRender(bool firstRender) { } - protected virtual System.Threading.Tasks.Task OnAfterRenderAsync(bool firstRender) { throw null; } - protected virtual void OnInitialized() { } - protected virtual System.Threading.Tasks.Task OnInitializedAsync() { throw null; } - protected virtual void OnParametersSet() { } - protected virtual System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } - public virtual System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - protected virtual bool ShouldRender() { throw null; } - protected void StateHasChanged() { } - } - public abstract partial class Dispatcher - { - protected Dispatcher() { } - public void AssertAccess() { } - public abstract bool CheckAccess(); - public static Microsoft.AspNetCore.Components.Dispatcher CreateDefault() { throw null; } - public abstract System.Threading.Tasks.Task InvokeAsync(System.Action workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func> workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func workItem); - protected void OnUnhandledException(System.UnhandledExceptionEventArgs e) { } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ElementReference - { - private readonly object _dummy; - public ElementReference(string id) { throw null; } - public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallback - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; - public static readonly Microsoft.AspNetCore.Components.EventCallbackFactory Factory; - public EventCallback(Microsoft.AspNetCore.Components.IHandleEvent receiver, System.MulticastDelegate @delegate) { throw null; } - public bool HasDelegate { get { throw null; } } - public System.Threading.Tasks.Task InvokeAsync(object arg) { throw null; } - } - public sealed partial class EventCallbackFactory - { - public EventCallbackFactory() { } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Action callback, TValue value) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Func callback, TValue value) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - } - public static partial class EventCallbackFactoryBinderExtensions - { - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, bool existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, decimal existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, double existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, int existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, long existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, bool? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset? existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime? existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, decimal? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, double? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, int? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, long? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, float? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, float existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, string existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, T existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - } - public static partial class EventCallbackFactoryEventArgsExtensions - { - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallbackWorkItem - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallbackWorkItem Empty; - public EventCallbackWorkItem(System.MulticastDelegate @delegate) { throw null; } - public System.Threading.Tasks.Task InvokeAsync(object arg) { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallback - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; - public EventCallback(Microsoft.AspNetCore.Components.IHandleEvent receiver, System.MulticastDelegate @delegate) { throw null; } - public bool HasDelegate { get { throw null; } } - public System.Threading.Tasks.Task InvokeAsync(TValue arg) { throw null; } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] - public sealed partial class EventHandlerAttribute : System.Attribute - { - public EventHandlerAttribute(string attributeName, System.Type eventArgsType) { } - public EventHandlerAttribute(string attributeName, System.Type eventArgsType, bool enableStopPropagation, bool enablePreventDefault) { } - public string AttributeName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public bool EnablePreventDefault { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public bool EnableStopPropagation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public System.Type EventArgsType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial interface IComponent - { - void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle); - System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters); - } - public partial interface IHandleAfterRender - { - System.Threading.Tasks.Task OnAfterRenderAsync(); - } - public partial interface IHandleEvent - { - System.Threading.Tasks.Task HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem item, object arg); - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class InjectAttribute : System.Attribute - { - public InjectAttribute() { } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)] - public sealed partial class LayoutAttribute : System.Attribute - { - public LayoutAttribute(System.Type layoutType) { } - public System.Type LayoutType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class LayoutComponentBase : Microsoft.AspNetCore.Components.ComponentBase - { - protected LayoutComponentBase() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class LayoutView : Microsoft.AspNetCore.Components.IComponent - { - public LayoutView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type Layout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } - public sealed partial class LocationChangeException : System.Exception - { - public LocationChangeException(string message, System.Exception innerException) { } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct MarkupString - { - private readonly object _dummy; - public MarkupString(string value) { throw null; } - public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public static explicit operator Microsoft.AspNetCore.Components.MarkupString (string value) { throw null; } - public override string ToString() { throw null; } - } - public partial class NavigationException : System.Exception - { - public NavigationException(string uri) { } - public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class NavigationManager - { - protected NavigationManager() { } - public string BaseUri { get { throw null; } protected set { } } - public string Uri { get { throw null; } protected set { } } - public event System.EventHandler LocationChanged { add { } remove { } } - protected virtual void EnsureInitialized() { } - protected void Initialize(string baseUri, string uri) { } - public void NavigateTo(string uri, bool forceLoad = false) { } - protected abstract void NavigateToCore(string uri, bool forceLoad); - protected void NotifyLocationChanged(bool isInterceptedLink) { } - public System.Uri ToAbsoluteUri(string relativeUri) { throw null; } - public string ToBaseRelativePath(string uri) { throw null; } - } - public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - protected OwningComponentBase() { } - protected bool IsDisposed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - protected System.IServiceProvider ScopedServices { get { throw null; } } - protected virtual void Dispose(bool disposing) { } - void System.IDisposable.Dispose() { } - } - public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.OwningComponentBase, System.IDisposable - { - protected OwningComponentBase() { } - protected TService Service { get { throw null; } } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class ParameterAttribute : System.Attribute - { - public ParameterAttribute() { } - public bool CaptureUnmatchedValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ParameterValue - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public bool Cascading { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ParameterView - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public static Microsoft.AspNetCore.Components.ParameterView Empty { get { throw null; } } - public static Microsoft.AspNetCore.Components.ParameterView FromDictionary(System.Collections.Generic.IDictionary parameters) { throw null; } - public Microsoft.AspNetCore.Components.ParameterView.Enumerator GetEnumerator() { throw null; } - public TValue GetValueOrDefault(string parameterName) { throw null; } - public TValue GetValueOrDefault(string parameterName, TValue defaultValue) { throw null; } - public void SetParameterProperties(object target) { } - public System.Collections.Generic.IReadOnlyDictionary ToDictionary() { throw null; } - public bool TryGetValue(string parameterName, out TValue result) { throw null; } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public partial struct Enumerator - { - private object _dummy; - private int _dummyPrimitive; - public Microsoft.AspNetCore.Components.ParameterValue Current { get { throw null; } } - public bool MoveNext() { throw null; } - } - } - public delegate void RenderFragment(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder); - public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(TValue value); - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderHandle - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get { throw null; } } - public bool IsInitialized { get { throw null; } } - public void Render(Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=false)] - public sealed partial class RouteAttribute : System.Attribute - { - public RouteAttribute(string template) { } - public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public sealed partial class RouteData - { - public RouteData(System.Type pageType, System.Collections.Generic.IReadOnlyDictionary routeValues) { } - public System.Type PageType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public System.Collections.Generic.IReadOnlyDictionary RouteValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial class RouteView : Microsoft.AspNetCore.Components.IComponent - { - public RouteView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type DefaultLayout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RouteData RouteData { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - protected virtual void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } -} -namespace Microsoft.AspNetCore.Components.CompilerServices -{ - public static partial class RuntimeHelpers - { - public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Action callback, T value) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Func callback, T value) { throw null; } - public static T TypeCheck(T value) { throw null; } - } -} -namespace Microsoft.AspNetCore.Components.Rendering -{ - public sealed partial class RenderTreeBuilder : System.IDisposable - { - public RenderTreeBuilder() { } - public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddAttribute(int sequence, string name, bool value) { } - public void AddAttribute(int sequence, string name, System.MulticastDelegate value) { } - public void AddAttribute(int sequence, string name, object value) { } - public void AddAttribute(int sequence, string name, string value) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddComponentReferenceCapture(int sequence, System.Action componentReferenceCaptureAction) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString markupContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment) { } - public void AddContent(int sequence, object textContent) { } - public void AddContent(int sequence, string textContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment, TValue value) { } - public void AddElementReferenceCapture(int sequence, System.Action elementReferenceCaptureAction) { } - public void AddMarkupContent(int sequence, string markupContent) { } - public void AddMultipleAttributes(int sequence, System.Collections.Generic.IEnumerable> attributes) { } - public void Clear() { } - public void CloseComponent() { } - public void CloseElement() { } - public void CloseRegion() { } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetFrames() { throw null; } - public void OpenComponent(int sequence, System.Type componentType) { } - public void OpenComponent(int sequence) where TComponent : Microsoft.AspNetCore.Components.IComponent { } - public void OpenElement(int sequence, string elementName) { } - public void OpenRegion(int sequence) { } - public void SetKey(object value) { } - public void SetUpdatesAttributeName(string updatesAttributeName) { } - void System.IDisposable.Dispose() { } - } -} -namespace Microsoft.AspNetCore.Components.RenderTree -{ - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ArrayBuilderSegment : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public T[] Array { get { throw null; } } - public int Count { get { throw null; } } - public T this[int index] { get { throw null; } } - public int Offset { get { throw null; } } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ArrayRange - { - public readonly T[] Array; - public readonly int Count; - public ArrayRange(T[] array, int count) { throw null; } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange Clone() { throw null; } - } - public partial class EventFieldInfo - { - public EventFieldInfo() { } - public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public object FieldValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderBatch - { - private readonly object _dummy; - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange DisposedComponentIDs { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange DisposedEventHandlerIDs { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange ReferenceFrames { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange UpdatedComponents { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class Renderer : System.IDisposable - { - public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } - public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; } - public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } - protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } - public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } - public void Dispose() { } - protected virtual void Dispose(bool disposing) { } - protected Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetCurrentRenderTreeFrames(int componentId) { throw null; } - protected abstract void HandleException(System.Exception exception); - protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; } - protected virtual void ProcessPendingRender() { } - protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId) { throw null; } - [System.Diagnostics.DebuggerStepThroughAttribute] - protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; } - protected abstract System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.RenderTree.RenderBatch renderBatch); - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderTreeDiff - { - public readonly int ComponentId; - public readonly Microsoft.AspNetCore.Components.RenderTree.ArrayBuilderSegment Edits; - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)] - public readonly partial struct RenderTreeEdit - { - [System.Runtime.InteropServices.FieldOffsetAttribute(8)] - public readonly int MoveToSiblingIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(8)] - public readonly int ReferenceFrameIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(16)] - public readonly string RemovedAttributeName; - [System.Runtime.InteropServices.FieldOffsetAttribute(4)] - public readonly int SiblingIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(0)] - public readonly Microsoft.AspNetCore.Components.RenderTree.RenderTreeEditType Type; - } - public enum RenderTreeEditType - { - PrependFrame = 1, - RemoveFrame = 2, - SetAttribute = 3, - RemoveAttribute = 4, - UpdateText = 5, - StepIn = 6, - StepOut = 7, - UpdateMarkup = 8, - PermutationListEntry = 9, - PermutationListEnd = 10, - } - public enum RenderTreeFrameType : short - { - None = (short)0, - Element = (short)1, - Text = (short)2, - Attribute = (short)3, - Component = (short)4, - Region = (short)5, - ElementReferenceCapture = (short)6, - ComponentReferenceCapture = (short)7, - Markup = (short)8, - } -} -namespace Microsoft.AspNetCore.Components.Routing -{ - public partial interface IHostEnvironmentNavigationManager - { - void Initialize(string baseUri, string uri); - } - public partial interface INavigationInterception - { - System.Threading.Tasks.Task EnableNavigationInterceptionAsync(); - } - public partial class LocationChangedEventArgs : System.EventArgs - { - public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { } - public bool IsNavigationIntercepted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial class Router : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, System.IDisposable - { - public Router() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Collections.Generic.IEnumerable AdditionalAssemblies { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Found { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public void Dispose() { } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() { throw null; } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } -} diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs deleted file mode 100644 index 0f6b69993535..000000000000 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs +++ /dev/null @@ -1,58 +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.Runtime.InteropServices; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - // https://github.com/dotnet/arcade/pull/2033 - [StructLayout(LayoutKind.Explicit, Pack = 4)] - public readonly partial struct RenderTreeFrame - { - [FieldOffset(0)] public readonly int Sequence; - - [FieldOffset(4)] public readonly RenderTreeFrameType FrameType; - - [FieldOffset(8)] public readonly int ElementSubtreeLength; - - [FieldOffset(16)] public readonly string ElementName; - - [FieldOffset(24)] public readonly object ElementKey; - - [FieldOffset(16)] public readonly string TextContent; - - [FieldOffset(8)] public readonly ulong AttributeEventHandlerId; - - [FieldOffset(16)] public readonly string AttributeName; - - [FieldOffset(24)] public readonly object AttributeValue; - - [FieldOffset(32)] public readonly string AttributeEventUpdatesAttributeName; - - [FieldOffset(8)] public readonly int ComponentSubtreeLength; - - [FieldOffset(12)] public readonly int ComponentId; - - [FieldOffset(16)] public readonly Type ComponentType; - - [FieldOffset(32)] public readonly object ComponentKey; - - public IComponent Component => null; - - [FieldOffset(8)] public readonly int RegionSubtreeLength; - - [FieldOffset(16)] public readonly string ElementReferenceCaptureId; - - [FieldOffset(24)] public readonly Action ElementReferenceCaptureAction; - - [FieldOffset(8)] public readonly int ComponentReferenceCaptureParentFrameIndex; - - [FieldOffset(16)] public readonly Action ComponentReferenceCaptureAction; - - [FieldOffset(16)] public readonly string MarkupContent; - - public override string ToString() => null; - } -} diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs deleted file mode 100644 index c4a48435b453..000000000000 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs +++ /dev/null @@ -1,550 +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 -{ - public static partial class BindConverter - { - public static bool FormatValue(bool value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(decimal value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(double value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(int value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(long value, System.Globalization.CultureInfo culture = null) { throw null; } - public static bool? FormatValue(bool? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTimeOffset? value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(System.DateTime? value, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(decimal? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(double? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(int? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(long? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(float? value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(float value, System.Globalization.CultureInfo culture = null) { throw null; } - public static string FormatValue(string value, System.Globalization.CultureInfo culture = null) { throw null; } - public static object FormatValue(T value, System.Globalization.CultureInfo culture = null) { throw null; } - public static bool TryConvertToBool(object obj, System.Globalization.CultureInfo culture, out bool value) { throw null; } - public static bool TryConvertToDateTime(object obj, System.Globalization.CultureInfo culture, out System.DateTime value) { throw null; } - public static bool TryConvertToDateTime(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTime value) { throw null; } - public static bool TryConvertToDateTimeOffset(object obj, System.Globalization.CultureInfo culture, out System.DateTimeOffset value) { throw null; } - public static bool TryConvertToDateTimeOffset(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTimeOffset value) { throw null; } - public static bool TryConvertToDecimal(object obj, System.Globalization.CultureInfo culture, out decimal value) { throw null; } - public static bool TryConvertToDouble(object obj, System.Globalization.CultureInfo culture, out double value) { throw null; } - public static bool TryConvertToFloat(object obj, System.Globalization.CultureInfo culture, out float value) { throw null; } - public static bool TryConvertToInt(object obj, System.Globalization.CultureInfo culture, out int value) { throw null; } - public static bool TryConvertToLong(object obj, System.Globalization.CultureInfo culture, out long value) { throw null; } - public static bool TryConvertToNullableBool(object obj, System.Globalization.CultureInfo culture, out bool? value) { throw null; } - public static bool TryConvertToNullableDateTime(object obj, System.Globalization.CultureInfo culture, out System.DateTime? value) { throw null; } - public static bool TryConvertToNullableDateTime(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTime? value) { throw null; } - public static bool TryConvertToNullableDateTimeOffset(object obj, System.Globalization.CultureInfo culture, out System.DateTimeOffset? value) { throw null; } - public static bool TryConvertToNullableDateTimeOffset(object obj, System.Globalization.CultureInfo culture, string format, out System.DateTimeOffset? value) { throw null; } - public static bool TryConvertToNullableDecimal(object obj, System.Globalization.CultureInfo culture, out decimal? value) { throw null; } - public static bool TryConvertToNullableDouble(object obj, System.Globalization.CultureInfo culture, out double? value) { throw null; } - public static bool TryConvertToNullableFloat(object obj, System.Globalization.CultureInfo culture, out float? value) { throw null; } - public static bool TryConvertToNullableInt(object obj, System.Globalization.CultureInfo culture, out int? value) { throw null; } - public static bool TryConvertToNullableLong(object obj, System.Globalization.CultureInfo culture, out long? value) { throw null; } - public static bool TryConvertToString(object obj, System.Globalization.CultureInfo culture, out string value) { throw null; } - public static bool TryConvertTo(object obj, System.Globalization.CultureInfo culture, out T value) { throw null; } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] - public sealed partial class BindElementAttribute : System.Attribute - { - public BindElementAttribute(string element, string suffix, string valueAttribute, string changeAttribute) { } - public string ChangeAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Element { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Suffix { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class CascadingParameterAttribute : System.Attribute - { - public CascadingParameterAttribute() { } - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class CascadingValue : Microsoft.AspNetCore.Components.IComponent - { - public CascadingValue() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public bool IsFixed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } - public partial class ChangeEventArgs : System.EventArgs - { - public ChangeEventArgs() { } - public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public abstract partial class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent - { - public ComponentBase() { } - protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected System.Threading.Tasks.Task InvokeAsync(System.Action workItem) { throw null; } - protected System.Threading.Tasks.Task InvokeAsync(System.Func workItem) { throw null; } - void Microsoft.AspNetCore.Components.IComponent.Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() { throw null; } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem callback, object arg) { throw null; } - protected virtual void OnAfterRender(bool firstRender) { } - protected virtual System.Threading.Tasks.Task OnAfterRenderAsync(bool firstRender) { throw null; } - protected virtual void OnInitialized() { } - protected virtual System.Threading.Tasks.Task OnInitializedAsync() { throw null; } - protected virtual void OnParametersSet() { } - protected virtual System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } - public virtual System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - protected virtual bool ShouldRender() { throw null; } - protected void StateHasChanged() { } - } - public abstract partial class Dispatcher - { - protected Dispatcher() { } - public void AssertAccess() { } - public abstract bool CheckAccess(); - public static Microsoft.AspNetCore.Components.Dispatcher CreateDefault() { throw null; } - public abstract System.Threading.Tasks.Task InvokeAsync(System.Action workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func> workItem); - public abstract System.Threading.Tasks.Task InvokeAsync(System.Func workItem); - protected void OnUnhandledException(System.UnhandledExceptionEventArgs e) { } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ElementReference - { - private readonly object _dummy; - public ElementReference(string id) { throw null; } - public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallback - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; - public static readonly Microsoft.AspNetCore.Components.EventCallbackFactory Factory; - public EventCallback(Microsoft.AspNetCore.Components.IHandleEvent receiver, System.MulticastDelegate @delegate) { throw null; } - public bool HasDelegate { get { throw null; } } - public System.Threading.Tasks.Task InvokeAsync(object arg) { throw null; } - } - public sealed partial class EventCallbackFactory - { - public EventCallbackFactory() { } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Action callback, TValue value) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Func callback, TValue value) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - } - public static partial class EventCallbackFactoryBinderExtensions - { - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, bool existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, decimal existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, double existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, int existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, long existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, bool? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTimeOffset? existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateTime? existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, decimal? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, double? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, int? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, long? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, float? existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, float existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, string existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, T existingValue, System.Globalization.CultureInfo culture = null) { throw null; } - } - public static partial class EventCallbackFactoryEventArgsExtensions - { - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallbackWorkItem - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallbackWorkItem Empty; - public EventCallbackWorkItem(System.MulticastDelegate @delegate) { throw null; } - public System.Threading.Tasks.Task InvokeAsync(object arg) { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallback - { - private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; - public EventCallback(Microsoft.AspNetCore.Components.IHandleEvent receiver, System.MulticastDelegate @delegate) { throw null; } - public bool HasDelegate { get { throw null; } } - public System.Threading.Tasks.Task InvokeAsync(TValue arg) { throw null; } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] - public sealed partial class EventHandlerAttribute : System.Attribute - { - public EventHandlerAttribute(string attributeName, System.Type eventArgsType) { } - public EventHandlerAttribute(string attributeName, System.Type eventArgsType, bool enableStopPropagation, bool enablePreventDefault) { } - public string AttributeName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public bool EnablePreventDefault { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public bool EnableStopPropagation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public System.Type EventArgsType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial interface IComponent - { - void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle); - System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters); - } - public partial interface IHandleAfterRender - { - System.Threading.Tasks.Task OnAfterRenderAsync(); - } - public partial interface IHandleEvent - { - System.Threading.Tasks.Task HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem item, object arg); - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class InjectAttribute : System.Attribute - { - public InjectAttribute() { } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)] - public sealed partial class LayoutAttribute : System.Attribute - { - public LayoutAttribute(System.Type layoutType) { } - public System.Type LayoutType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class LayoutComponentBase : Microsoft.AspNetCore.Components.ComponentBase - { - protected LayoutComponentBase() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class LayoutView : Microsoft.AspNetCore.Components.IComponent - { - public LayoutView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type Layout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } - public sealed partial class LocationChangeException : System.Exception - { - public LocationChangeException(string message, System.Exception innerException) { } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct MarkupString - { - private readonly object _dummy; - public MarkupString(string value) { throw null; } - public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public static explicit operator Microsoft.AspNetCore.Components.MarkupString (string value) { throw null; } - public override string ToString() { throw null; } - } - public partial class NavigationException : System.Exception - { - public NavigationException(string uri) { } - public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class NavigationManager - { - protected NavigationManager() { } - public string BaseUri { get { throw null; } protected set { } } - public string Uri { get { throw null; } protected set { } } - public event System.EventHandler LocationChanged { add { } remove { } } - protected virtual void EnsureInitialized() { } - protected void Initialize(string baseUri, string uri) { } - public void NavigateTo(string uri, bool forceLoad = false) { } - protected abstract void NavigateToCore(string uri, bool forceLoad); - protected void NotifyLocationChanged(bool isInterceptedLink) { } - public System.Uri ToAbsoluteUri(string relativeUri) { throw null; } - public string ToBaseRelativePath(string uri) { throw null; } - } - public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - protected OwningComponentBase() { } - protected bool IsDisposed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - protected System.IServiceProvider ScopedServices { get { throw null; } } - protected virtual void Dispose(bool disposing) { } - void System.IDisposable.Dispose() { } - } - public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.OwningComponentBase, System.IDisposable - { - protected OwningComponentBase() { } - protected TService Service { get { throw null; } } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] - public sealed partial class ParameterAttribute : System.Attribute - { - public ParameterAttribute() { } - public bool CaptureUnmatchedValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ParameterValue - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public bool Cascading { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ParameterView - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public static Microsoft.AspNetCore.Components.ParameterView Empty { get { throw null; } } - public static Microsoft.AspNetCore.Components.ParameterView FromDictionary(System.Collections.Generic.IDictionary parameters) { throw null; } - public Microsoft.AspNetCore.Components.ParameterView.Enumerator GetEnumerator() { throw null; } - public TValue GetValueOrDefault(string parameterName) { throw null; } - public TValue GetValueOrDefault(string parameterName, TValue defaultValue) { throw null; } - public void SetParameterProperties(object target) { } - public System.Collections.Generic.IReadOnlyDictionary ToDictionary() { throw null; } - public bool TryGetValue(string parameterName, out TValue result) { throw null; } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public partial struct Enumerator - { - private object _dummy; - private int _dummyPrimitive; - public Microsoft.AspNetCore.Components.ParameterValue Current { get { throw null; } } - public bool MoveNext() { throw null; } - } - } - public delegate void RenderFragment(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder); - public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(TValue value); - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderHandle - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get { throw null; } } - public bool IsInitialized { get { throw null; } } - public void Render(Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } - } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=false)] - public sealed partial class RouteAttribute : System.Attribute - { - public RouteAttribute(string template) { } - public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public sealed partial class RouteData - { - public RouteData(System.Type pageType, System.Collections.Generic.IReadOnlyDictionary routeValues) { } - public System.Type PageType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public System.Collections.Generic.IReadOnlyDictionary RouteValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial class RouteView : Microsoft.AspNetCore.Components.IComponent - { - public RouteView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type DefaultLayout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RouteData RouteData { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - protected virtual void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } -} -namespace Microsoft.AspNetCore.Components.CompilerServices -{ - public static partial class RuntimeHelpers - { - public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Action callback, T value) { throw null; } - public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Func callback, T value) { throw null; } - public static T TypeCheck(T value) { throw null; } - } -} -namespace Microsoft.AspNetCore.Components.Rendering -{ - public sealed partial class RenderTreeBuilder : System.IDisposable - { - public RenderTreeBuilder() { } - public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddAttribute(int sequence, string name, bool value) { } - public void AddAttribute(int sequence, string name, System.MulticastDelegate value) { } - public void AddAttribute(int sequence, string name, object value) { } - public void AddAttribute(int sequence, string name, string value) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddComponentReferenceCapture(int sequence, System.Action componentReferenceCaptureAction) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString markupContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment) { } - public void AddContent(int sequence, object textContent) { } - public void AddContent(int sequence, string textContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment, TValue value) { } - public void AddElementReferenceCapture(int sequence, System.Action elementReferenceCaptureAction) { } - public void AddMarkupContent(int sequence, string markupContent) { } - public void AddMultipleAttributes(int sequence, System.Collections.Generic.IEnumerable> attributes) { } - public void Clear() { } - public void CloseComponent() { } - public void CloseElement() { } - public void CloseRegion() { } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetFrames() { throw null; } - public void OpenComponent(int sequence, System.Type componentType) { } - public void OpenComponent(int sequence) where TComponent : Microsoft.AspNetCore.Components.IComponent { } - public void OpenElement(int sequence, string elementName) { } - public void OpenRegion(int sequence) { } - public void SetKey(object value) { } - public void SetUpdatesAttributeName(string updatesAttributeName) { } - void System.IDisposable.Dispose() { } - } -} -namespace Microsoft.AspNetCore.Components.RenderTree -{ - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ArrayBuilderSegment : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable - { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public T[] Array { get { throw null; } } - public int Count { get { throw null; } } - public T this[int index] { get { throw null; } } - public int Offset { get { throw null; } } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ArrayRange - { - public readonly T[] Array; - public readonly int Count; - public ArrayRange(T[] array, int count) { throw null; } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange Clone() { throw null; } - } - public partial class EventFieldInfo - { - public EventFieldInfo() { } - public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public object FieldValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderBatch - { - private readonly object _dummy; - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange DisposedComponentIDs { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange DisposedEventHandlerIDs { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange ReferenceFrames { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange UpdatedComponents { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public abstract partial class Renderer : System.IDisposable - { - public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } - public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; } - public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } - protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } - public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } - public void Dispose() { } - protected virtual void Dispose(bool disposing) { } - protected Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetCurrentRenderTreeFrames(int componentId) { throw null; } - protected abstract void HandleException(System.Exception exception); - protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; } - protected virtual void ProcessPendingRender() { } - protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId) { throw null; } - [System.Diagnostics.DebuggerStepThroughAttribute] - protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; } - protected abstract System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.RenderTree.RenderBatch renderBatch); - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct RenderTreeDiff - { - public readonly int ComponentId; - public readonly Microsoft.AspNetCore.Components.RenderTree.ArrayBuilderSegment Edits; - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)] - public readonly partial struct RenderTreeEdit - { - [System.Runtime.InteropServices.FieldOffsetAttribute(8)] - public readonly int MoveToSiblingIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(8)] - public readonly int ReferenceFrameIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(16)] - public readonly string RemovedAttributeName; - [System.Runtime.InteropServices.FieldOffsetAttribute(4)] - public readonly int SiblingIndex; - [System.Runtime.InteropServices.FieldOffsetAttribute(0)] - public readonly Microsoft.AspNetCore.Components.RenderTree.RenderTreeEditType Type; - } - public enum RenderTreeEditType - { - PrependFrame = 1, - RemoveFrame = 2, - SetAttribute = 3, - RemoveAttribute = 4, - UpdateText = 5, - StepIn = 6, - StepOut = 7, - UpdateMarkup = 8, - PermutationListEntry = 9, - PermutationListEnd = 10, - } - public enum RenderTreeFrameType : short - { - None = (short)0, - Element = (short)1, - Text = (short)2, - Attribute = (short)3, - Component = (short)4, - Region = (short)5, - ElementReferenceCapture = (short)6, - ComponentReferenceCapture = (short)7, - Markup = (short)8, - } -} -namespace Microsoft.AspNetCore.Components.Routing -{ - public partial interface IHostEnvironmentNavigationManager - { - void Initialize(string baseUri, string uri); - } - public partial interface INavigationInterception - { - System.Threading.Tasks.Task EnableNavigationInterceptionAsync(); - } - public partial class LocationChangedEventArgs : System.EventArgs - { - public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { } - public bool IsNavigationIntercepted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public partial class Router : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, System.IDisposable - { - public Router() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Collections.Generic.IEnumerable AdditionalAssemblies { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Found { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public void Dispose() { } - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() { throw null; } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } -} diff --git a/src/Components/Components/src/BindConverter.cs b/src/Components/Components/src/BindConverter.cs deleted file mode 100644 index f77689bde2bf..000000000000 --- a/src/Components/Components/src/BindConverter.cs +++ /dev/null @@ -1,1418 +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.Concurrent; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Performs conversions during binding. - /// - // - // Perf: our conversion routines present a regular API surface that allows us to specialize on types to avoid boxing. - // for instance, many of these types could be cast to IFormattable to do the appropriate formatting, but that's going - // to allocate. - public static class BindConverter - { - private static object BoxedTrue = true; - private static object BoxedFalse = false; - - private delegate object BindFormatter(T value, CultureInfo culture); - private delegate object BindFormatterWithFormat(T value, CultureInfo culture, string format); - - internal delegate bool BindParser(object obj, CultureInfo culture, out T value); - internal delegate bool BindParserWithFormat(object obj, CultureInfo culture, string format, out T value); - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(string value, CultureInfo culture = null) => FormatStringValueCore(value, culture); - - private static string FormatStringValueCore(string value, CultureInfo culture) - { - return value; - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static bool FormatValue(bool value, CultureInfo culture = null) - { - // Formatting for bool is special-cased. We need to produce a boolean value for conditional attributes - // to work. - return value; - } - - // Used with generics - private static object FormatBoolValueCore(bool value, CultureInfo culture) - { - // Formatting for bool is special-cased. We need to produce a boolean value for conditional attributes - // to work. - return value ? BoxedTrue : BoxedFalse; - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static bool? FormatValue(bool? value, CultureInfo culture = null) - { - // Formatting for bool is special-cased. We need to produce a boolean value for conditional attributes - // to work. - return value == null ? (bool?)null : value.Value; - } - - // Used with generics - private static object FormatNullableBoolValueCore(bool? value, CultureInfo culture) - { - // Formatting for bool is special-cased. We need to produce a boolean value for conditional attributes - // to work. - return value == null ? null : value.Value ? BoxedTrue : BoxedFalse; - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(int value, CultureInfo culture = null) => FormatIntValueCore(value, culture); - - private static string FormatIntValueCore(int value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(int? value, CultureInfo culture = null) => FormatNullableIntValueCore(value, culture); - - private static string FormatNullableIntValueCore(int? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(long value, CultureInfo culture = null) => FormatLongValueCore(value, culture); - - private static string FormatLongValueCore(long value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(long? value, CultureInfo culture = null) => FormatNullableLongValueCore(value, culture); - - private static string FormatNullableLongValueCore(long? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(float value, CultureInfo culture = null) => FormatFloatValueCore(value, culture); - - private static string FormatFloatValueCore(float value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(float? value, CultureInfo culture = null) => FormatNullableFloatValueCore(value, culture); - - private static string FormatNullableFloatValueCore(float? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(double value, CultureInfo culture = null) => FormatDoubleValueCore(value, culture); - - private static string FormatDoubleValueCore(double value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(double? value, CultureInfo culture = null) => FormatNullableDoubleValueCore(value, culture); - - private static string FormatNullableDoubleValueCore(double? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided for inclusion in an attribute. - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(decimal value, CultureInfo culture = null) => FormatDecimalValueCore(value, culture); - - private static string FormatDecimalValueCore(decimal value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(decimal? value, CultureInfo culture = null) => FormatNullableDecimalValueCore(value, culture); - - private static string FormatNullableDecimalValueCore(decimal? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTime value, CultureInfo culture = null) => FormatDateTimeValueCore(value, format: null, culture); - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// The format to use. Provided to . - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTime value, string format, CultureInfo culture = null) => FormatDateTimeValueCore(value, format, culture); - - private static string FormatDateTimeValueCore(DateTime value, string format, CultureInfo culture) - { - if (format != null) - { - return value.ToString(format, culture ?? CultureInfo.CurrentCulture); - } - - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - private static string FormatDateTimeValueCore(DateTime value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTime? value, CultureInfo culture = null) => FormatNullableDateTimeValueCore(value, format: null, culture); - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// The format to use. Provided to . - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTime? value, string format, CultureInfo culture = null) => FormatNullableDateTimeValueCore(value, format, culture); - - private static string FormatNullableDateTimeValueCore(DateTime? value, string format, CultureInfo culture) - { - if (value == null) - { - return null; - } - - if (format != null) - { - return value.Value.ToString(format, culture ?? CultureInfo.CurrentCulture); - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - private static string FormatNullableDateTimeValueCore(DateTime? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTimeOffset value, CultureInfo culture = null) => FormatDateTimeOffsetValueCore(value, format: null, culture); - - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// The format to use. Provided to . - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTimeOffset value, string format, CultureInfo culture = null) => FormatDateTimeOffsetValueCore(value, format, culture); - - private static string FormatDateTimeOffsetValueCore(DateTimeOffset value, string format, CultureInfo culture) - { - if (format != null) - { - return value.ToString(format, culture ?? CultureInfo.CurrentCulture); - } - - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - private static string FormatDateTimeOffsetValueCore(DateTimeOffset value, CultureInfo culture) - { - return value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTimeOffset? value, CultureInfo culture = null) => FormatNullableDateTimeOffsetValueCore(value, format: null, culture); - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// The format to use. Provided to . - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static string FormatValue(DateTimeOffset? value, string format, CultureInfo culture = null) => FormatNullableDateTimeOffsetValueCore(value, format, culture); - - private static string FormatNullableDateTimeOffsetValueCore(DateTimeOffset? value, string format, CultureInfo culture) - { - if (value == null) - { - return null; - } - - if (format != null) - { - return value.Value.ToString(format, culture ?? CultureInfo.CurrentCulture); - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - private static string FormatNullableDateTimeOffsetValueCore(DateTimeOffset? value, CultureInfo culture) - { - if (value == null) - { - return null; - } - - return value.Value.ToString(culture ?? CultureInfo.CurrentCulture); - } - - private static string FormatEnumValueCore(T value, CultureInfo culture) where T : struct, Enum - { - return value.ToString(); // The overload that acccepts a culture is [Obsolete] - } - - private static string FormatNullableEnumValueCore(T? value, CultureInfo culture) where T : struct, Enum - { - if (value == null) - { - return null; - } - - return value.Value.ToString(); // The overload that acccepts a culture is [Obsolete] - } - - /// - /// Formats the provided as a . - /// - /// The value to format. - /// - /// The to use while formatting. Defaults to . - /// - /// The formatted value. - public static object FormatValue(T value, CultureInfo culture = null) - { - var formatter = FormatterDelegateCache.Get(); - return formatter(value, culture); - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToString(object obj, CultureInfo culture, out string value) - { - return ConvertToStringCore(obj, culture, out value); - } - - internal readonly static BindParser ConvertToString = ConvertToStringCore; - - private static bool ConvertToStringCore(object obj, CultureInfo culture, out string value) - { - // We expect the input to already be a string. - value = (string)obj; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToBool(object obj, CultureInfo culture, out bool value) - { - return ConvertToBoolCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableBool(object obj, CultureInfo culture, out bool? value) - { - return ConvertToNullableBoolCore(obj, culture, out value); - } - - internal static BindParser ConvertToBool = ConvertToBoolCore; - internal static BindParser ConvertToNullableBool = ConvertToNullableBoolCore; - - private static bool ConvertToBoolCore(object obj, CultureInfo culture, out bool value) - { - // We expect the input to already be a bool. - value = (bool)obj; - return true; - } - - private static bool ConvertToNullableBoolCore(object obj, CultureInfo culture, out bool? value) - { - // We expect the input to already be a bool. - value = (bool?)obj; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToInt(object obj, CultureInfo culture, out int value) - { - return ConvertToIntCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableInt(object obj, CultureInfo culture, out int? value) - { - return ConvertToNullableIntCore(obj, culture, out value); - } - - internal static BindParser ConvertToInt = ConvertToIntCore; - internal static BindParser ConvertToNullableInt = ConvertToNullableIntCore; - - private static bool ConvertToIntCore(object obj, CultureInfo culture, out int value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (!int.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableIntCore(object obj, CultureInfo culture, out int? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!int.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToLong(object obj, CultureInfo culture, out long value) - { - return ConvertToLongCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableLong(object obj, CultureInfo culture, out long? value) - { - return ConvertToNullableLongCore(obj, culture, out value); - } - - internal static BindParser ConvertToLong = ConvertToLongCore; - internal static BindParser ConvertToNullableLong = ConvertToNullableLongCore; - - private static bool ConvertToLongCore(object obj, CultureInfo culture, out long value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (!long.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableLongCore(object obj, CultureInfo culture, out long? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!long.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToFloat(object obj, CultureInfo culture, out float value) - { - return ConvertToFloatCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableFloat(object obj, CultureInfo culture, out float? value) - { - return ConvertToNullableFloatCore(obj, culture, out value); - } - - internal static BindParser ConvertToFloat = ConvertToFloatCore; - internal static BindParser ConvertToNullableFloat = ConvertToNullableFloatCore; - - private static bool ConvertToFloatCore(object obj, CultureInfo culture, out float value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (!float.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - if (float.IsInfinity(converted) || float.IsNaN(converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableFloatCore(object obj, CultureInfo culture, out float? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!float.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - if (float.IsInfinity(converted) || float.IsNaN(converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDouble(object obj, CultureInfo culture, out double value) - { - return ConvertToDoubleCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDouble(object obj, CultureInfo culture, out double? value) - { - return ConvertToNullableDoubleCore(obj, culture, out value); - } - - internal static BindParser ConvertToDoubleDelegate = ConvertToDoubleCore; - internal static BindParser ConvertToNullableDoubleDelegate = ConvertToNullableDoubleCore; - - private static bool ConvertToDoubleCore(object obj, CultureInfo culture, out double value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (!double.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - if (double.IsInfinity(converted) || double.IsNaN(converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableDoubleCore(object obj, CultureInfo culture, out double? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!double.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - if (double.IsInfinity(converted) || double.IsNaN(converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDecimal(object obj, CultureInfo culture, out decimal value) - { - return ConvertToDecimalCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDecimal(object obj, CultureInfo culture, out decimal? value) - { - return ConvertToNullableDecimalCore(obj, culture, out value); - } - - internal static BindParser ConvertToDecimal = ConvertToDecimalCore; - internal static BindParser ConvertToNullableDecimal = ConvertToNullableDecimalCore; - - private static bool ConvertToDecimalCore(object obj, CultureInfo culture, out decimal value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (!decimal.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableDecimalCore(object obj, CultureInfo culture, out decimal? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!decimal.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDateTime(object obj, CultureInfo culture, out DateTime value) - { - return ConvertToDateTimeCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The format string to use in conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDateTime(object obj, CultureInfo culture, string format, out DateTime value) - { - return ConvertToDateTimeCore(obj, culture, format, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDateTime(object obj, CultureInfo culture, out DateTime? value) - { - return ConvertToNullableDateTimeCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The format string to use in conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDateTime(object obj, CultureInfo culture, string format, out DateTime? value) - { - return ConvertToNullableDateTimeCore(obj, culture, format, out value); - } - - internal static BindParser ConvertToDateTime = ConvertToDateTimeCore; - internal static BindParserWithFormat ConvertToDateTimeWithFormat = ConvertToDateTimeCore; - internal static BindParser ConvertToNullableDateTime = ConvertToNullableDateTimeCore; - internal static BindParserWithFormat ConvertToNullableDateTimeWithFormat = ConvertToNullableDateTimeCore; - - private static bool ConvertToDateTimeCore(object obj, CultureInfo culture, out DateTime value) - { - return ConvertToDateTimeCore(obj, culture, format: null, out value); - } - - private static bool ConvertToDateTimeCore(object obj, CultureInfo culture, string format, out DateTime value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (format != null && DateTime.TryParseExact(text, format, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) - { - value = converted; - return true; - } - else if (format == null && DateTime.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out converted)) - { - value = converted; - return true; - } - - value = default; - return false; - } - - private static bool ConvertToNullableDateTimeCore(object obj, CultureInfo culture, out DateTime? value) - { - return ConvertToNullableDateTimeCore(obj, culture, format: null, out value); - } - - private static bool ConvertToNullableDateTimeCore(object obj, CultureInfo culture, string format, out DateTime? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (format != null && DateTime.TryParseExact(text, format, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) - { - value = converted; - return true; - } - else if (format == null && DateTime.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out converted)) - { - value = converted; - return true; - } - - value = default; - return false; - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDateTimeOffset(object obj, CultureInfo culture, out DateTimeOffset value) - { - return ConvertToDateTimeOffsetCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a . - /// - /// The object to convert. - /// The to use for conversion. - /// The format string to use in conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToDateTimeOffset(object obj, CultureInfo culture, string format, out DateTimeOffset value) - { - return ConvertToDateTimeOffsetCore(obj, culture, format, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDateTimeOffset(object obj, CultureInfo culture, out DateTimeOffset? value) - { - return ConvertToNullableDateTimeOffsetCore(obj, culture, out value); - } - - /// - /// Attempts to convert a value to a nullable . - /// - /// The object to convert. - /// The to use for conversion. - /// The format string to use in conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertToNullableDateTimeOffset(object obj, CultureInfo culture, string format, out DateTimeOffset? value) - { - return ConvertToNullableDateTimeOffsetCore(obj, culture, format, out value); - } - - internal static BindParser ConvertToDateTimeOffset = ConvertToDateTimeOffsetCore; - internal static BindParserWithFormat ConvertToDateTimeOffsetWithFormat = ConvertToDateTimeOffsetCore; - internal static BindParser ConvertToNullableDateTimeOffset = ConvertToNullableDateTimeOffsetCore; - internal static BindParserWithFormat ConvertToNullableDateTimeOffsetWithFormat = ConvertToNullableDateTimeOffsetCore; - - private static bool ConvertToDateTimeOffsetCore(object obj, CultureInfo culture, out DateTimeOffset value) - { - return ConvertToDateTimeOffsetCore(obj, culture, format: null, out value); - } - - private static bool ConvertToDateTimeOffsetCore(object obj, CultureInfo culture, string format, out DateTimeOffset value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return false; - } - - if (format != null && DateTimeOffset.TryParseExact(text, format, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) - { - value = converted; - return true; - } - else if (format == null && DateTimeOffset.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out converted)) - { - value = converted; - return true; - } - - value = default; - return false; - } - - private static bool ConvertToNullableDateTimeOffsetCore(object obj, CultureInfo culture, out DateTimeOffset? value) - { - return ConvertToNullableDateTimeOffsetCore(obj, culture, format: null, out value); - } - - private static bool ConvertToNullableDateTimeOffsetCore(object obj, CultureInfo culture, string format, out DateTimeOffset? value) - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (format != null && DateTimeOffset.TryParseExact(text, format, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) - { - value = converted; - return true; - } - else if (format == null && DateTimeOffset.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out converted)) - { - value = converted; - return true; - } - - value = default; - return false; - } - - private static bool ConvertToEnum(object obj, CultureInfo culture, out T value) where T : struct, Enum - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!Enum.TryParse(text, out var converted)) - { - value = default; - return false; - } - - if (!Enum.IsDefined(typeof(T), converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - private static bool ConvertToNullableEnum(object obj, CultureInfo culture, out T? value) where T : struct, Enum - { - var text = (string)obj; - if (string.IsNullOrEmpty(text)) - { - value = default; - return true; - } - - if (!Enum.TryParse(text, out var converted)) - { - value = default; - return false; - } - - if (!Enum.IsDefined(typeof(T), converted)) - { - value = default; - return false; - } - - value = converted; - return true; - } - - /// - /// Attempts to convert a value to a value of type . - /// - /// The object to convert. - /// The to use for conversion. - /// The converted value. - /// true if conversion is successful, otherwise false. - public static bool TryConvertTo(object obj, CultureInfo culture, out T value) - { - var converter = ParserDelegateCache.Get(); - return converter(obj, culture, out value); - } - - private static class FormatterDelegateCache - { - private readonly static ConcurrentDictionary _cache = new ConcurrentDictionary(); - - private static MethodInfo _formatEnumValue; - private static MethodInfo _formatNullableEnumValue; - - public static BindFormatter Get() - { - if (!_cache.TryGetValue(typeof(T), out var formattter)) - { - // We need to replicate all of the primitive cases that we handle here so that they will behave the same way. - // The result will be cached. - if (typeof(T) == typeof(string)) - { - formattter = (BindFormatter)FormatStringValueCore; - } - else if (typeof(T) == typeof(bool)) - { - formattter = (BindFormatter)FormatBoolValueCore; - } - else if (typeof(T) == typeof(bool?)) - { - formattter = (BindFormatter)FormatNullableBoolValueCore; - } - else if (typeof(T) == typeof(int)) - { - formattter = (BindFormatter)FormatIntValueCore; - } - else if (typeof(T) == typeof(int?)) - { - formattter = (BindFormatter)FormatNullableIntValueCore; - } - else if (typeof(T) == typeof(long)) - { - formattter = (BindFormatter)FormatLongValueCore; - } - else if (typeof(T) == typeof(long?)) - { - formattter = (BindFormatter)FormatNullableLongValueCore; - } - else if (typeof(T) == typeof(float)) - { - formattter = (BindFormatter)FormatFloatValueCore; - } - else if (typeof(T) == typeof(float?)) - { - formattter = (BindFormatter)FormatNullableFloatValueCore; - } - else if (typeof(T) == typeof(double)) - { - formattter = (BindFormatter)FormatDoubleValueCore; - } - else if (typeof(T) == typeof(double?)) - { - formattter = (BindFormatter)FormatNullableDoubleValueCore; - } - else if (typeof(T) == typeof(decimal)) - { - formattter = (BindFormatter)FormatDecimalValueCore; - } - else if (typeof(T) == typeof(decimal?)) - { - formattter = (BindFormatter)FormatNullableDecimalValueCore; - } - else if (typeof(T) == typeof(DateTime)) - { - formattter = (BindFormatter)FormatDateTimeValueCore; - } - else if (typeof(T) == typeof(DateTime?)) - { - formattter = (BindFormatter)FormatNullableDateTimeValueCore; - } - else if (typeof(T) == typeof(DateTimeOffset)) - { - formattter = (BindFormatter)FormatDateTimeOffsetValueCore; - } - else if (typeof(T) == typeof(DateTimeOffset?)) - { - formattter = (BindFormatter)FormatNullableDateTimeOffsetValueCore; - } - else if (typeof(T).IsEnum) - { - // We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse. - var method = _formatEnumValue ??= typeof(BindConverter).GetMethod(nameof(FormatEnumValueCore), BindingFlags.NonPublic | BindingFlags.Static); - formattter = method.MakeGenericMethod(typeof(T)).CreateDelegate(typeof(BindFormatter), target: null); - } - else if (Nullable.GetUnderlyingType(typeof(T)) is Type innerType && innerType.IsEnum) - { - // We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse. - var method = _formatNullableEnumValue ??= typeof(BindConverter).GetMethod(nameof(FormatNullableEnumValueCore), BindingFlags.NonPublic | BindingFlags.Static); - formattter = method.MakeGenericMethod(innerType).CreateDelegate(typeof(BindFormatter), target: null); - } - else - { - formattter = MakeTypeConverterFormatter(); - } - - _cache.TryAdd(typeof(T), formattter); - } - - return (BindFormatter)formattter; - } - - private static BindFormatter MakeTypeConverterFormatter() - { - var typeConverter = TypeDescriptor.GetConverter(typeof(T)); - if (typeConverter == null || !typeConverter.CanConvertTo(typeof(string))) - { - throw new InvalidOperationException( - $"The type '{typeof(T).FullName}' does not have an associated {typeof(TypeConverter).Name} that supports " + - $"conversion to a string. " + - $"Apply '{typeof(TypeConverterAttribute).Name}' to the type to register a converter."); - } - - return FormatWithTypeConverter; - - string FormatWithTypeConverter(T value, CultureInfo culture) - { - // We intentionally close-over the TypeConverter to cache it. The TypeDescriptor infrastructure is slow. - return typeConverter.ConvertToString(context: null, culture ?? CultureInfo.CurrentCulture, value); - } - } - } - - internal static class ParserDelegateCache - { - private readonly static ConcurrentDictionary _cache = new ConcurrentDictionary(); - - private static MethodInfo _convertToEnum; - private static MethodInfo _convertToNullableEnum; - - public static BindParser Get() - { - if (!_cache.TryGetValue(typeof(T), out var parser)) - { - // We need to replicate all of the primitive cases that we handle here so that they will behave the same way. - // The result will be cached. - if (typeof(T) == typeof(string)) - { - parser = ConvertToString; - } - else if (typeof(T) == typeof(bool)) - { - parser = ConvertToBool; - } - else if (typeof(T) == typeof(bool?)) - { - parser = ConvertToNullableBool; - } - else if (typeof(T) == typeof(int)) - { - parser = ConvertToInt; - } - else if (typeof(T) == typeof(int?)) - { - parser = ConvertToNullableInt; - } - else if (typeof(T) == typeof(long)) - { - parser = ConvertToLong; - } - else if (typeof(T) == typeof(long?)) - { - parser = ConvertToNullableLong; - } - else if (typeof(T) == typeof(float)) - { - parser = ConvertToFloat; - } - else if (typeof(T) == typeof(float?)) - { - parser = ConvertToNullableFloat; - } - else if (typeof(T) == typeof(double)) - { - parser = ConvertToDoubleDelegate; - } - else if (typeof(T) == typeof(double?)) - { - parser = ConvertToNullableDoubleDelegate; - } - else if (typeof(T) == typeof(decimal)) - { - parser = ConvertToDecimal; - } - else if (typeof(T) == typeof(decimal?)) - { - parser = ConvertToNullableDecimal; - } - else if (typeof(T) == typeof(DateTime)) - { - parser = ConvertToDateTime; - } - else if (typeof(T) == typeof(DateTime?)) - { - parser = ConvertToNullableDateTime; - } - else if (typeof(T) == typeof(DateTimeOffset)) - { - parser = ConvertToDateTime; - } - else if (typeof(T) == typeof(DateTimeOffset?)) - { - parser = ConvertToNullableDateTime; - } - else if (typeof(T).IsEnum) - { - // We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse. - var method = _convertToEnum ??= typeof(BindConverter).GetMethod(nameof(ConvertToEnum), BindingFlags.NonPublic | BindingFlags.Static); - parser = method.MakeGenericMethod(typeof(T)).CreateDelegate(typeof(BindParser), target: null); - } - else if (Nullable.GetUnderlyingType(typeof(T)) is Type innerType && innerType.IsEnum) - { - // We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse. - var method = _convertToNullableEnum ??= typeof(BindConverter).GetMethod(nameof(ConvertToNullableEnum), BindingFlags.NonPublic | BindingFlags.Static); - parser = method.MakeGenericMethod(innerType).CreateDelegate(typeof(BindParser), target: null); - } - else - { - parser = MakeTypeConverterConverter(); - } - - _cache.TryAdd(typeof(T), parser); - } - - return (BindParser)parser; - } - - private static BindParser MakeTypeConverterConverter() - { - var typeConverter = TypeDescriptor.GetConverter(typeof(T)); - if (typeConverter == null || !typeConverter.CanConvertFrom(typeof(string))) - { - throw new InvalidOperationException( - $"The type '{typeof(T).FullName}' does not have an associated {typeof(TypeConverter).Name} that supports " + - $"conversion from a string. " + - $"Apply '{typeof(TypeConverterAttribute).Name}' to the type to register a converter."); - } - - return ConvertWithTypeConverter; - - bool ConvertWithTypeConverter(object obj, CultureInfo culture, out T value) - { - // We intentionally close-over the TypeConverter to cache it. The TypeDescriptor infrastructure is slow. - var converted = typeConverter.ConvertFrom(context: null, culture ?? CultureInfo.CurrentCulture, obj); - if (converted == null) - { - value = default; - return true; - } - - value = (T)converted; - return true; - } - } - } - } -} diff --git a/src/Components/Components/src/BindElementAttribute.cs b/src/Components/Components/src/BindElementAttribute.cs deleted file mode 100644 index ffc17a6049ee..000000000000 --- a/src/Components/Components/src/BindElementAttribute.cs +++ /dev/null @@ -1,64 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Configures options for binding specific element types. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] - public sealed class BindElementAttribute : Attribute - { - /// - /// Constructs an instance of . - /// - /// The tag name of the element. - /// The suffix value. For example, set this to value for bind-value, or set this to null for bind. - /// The name of the value attribute to be bound. - /// The name of an attribute that will register an associated change event. - public BindElementAttribute(string element, string suffix, string valueAttribute, string changeAttribute) - { - if (element == null) - { - throw new ArgumentNullException(nameof(element)); - } - - if (valueAttribute == null) - { - throw new ArgumentNullException(nameof(valueAttribute)); - } - - if (changeAttribute == null) - { - throw new ArgumentNullException(nameof(changeAttribute)); - } - - Element = element; - ValueAttribute = valueAttribute; - ChangeAttribute = changeAttribute; - } - - /// - /// Gets the tag name of the element. - /// - public string Element { get; } - - /// - /// Gets the suffix value. - /// For example, this will be value to mean bind-value, or null to mean bind. - /// - public string Suffix { get; } - - /// - /// Gets the name of the value attribute to be bound. - /// - public string ValueAttribute { get; } - - /// - /// Gets the name of an attribute that will register an associated change event. - /// - public string ChangeAttribute { get; } - } -} diff --git a/src/Components/Components/src/CascadingParameterAttribute.cs b/src/Components/Components/src/CascadingParameterAttribute.cs deleted file mode 100644 index ca8113976b91..000000000000 --- a/src/Components/Components/src/CascadingParameterAttribute.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Denotes the target member as a cascading component parameter. Its value will be - /// supplied by the closest ancestor component that - /// supplies values with a compatible type and name. - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public sealed class CascadingParameterAttribute : Attribute - { - /// - /// If specified, the parameter value will be supplied by the closest - /// ancestor that supplies a value with - /// this name. - /// - /// If null, the parameter value will be supplied by the closest ancestor - /// that supplies a value with a compatible - /// type. - /// - public string Name { get; set; } - } -} diff --git a/src/Components/Components/src/CascadingParameterState.cs b/src/Components/Components/src/CascadingParameterState.cs deleted file mode 100644 index 8c3e445a86f9..000000000000 --- a/src/Components/Components/src/CascadingParameterState.cs +++ /dev/null @@ -1,129 +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.Reflection; -using Microsoft.AspNetCore.Components.Rendering; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Reflection; - -namespace Microsoft.AspNetCore.Components -{ - internal readonly struct CascadingParameterState - { - private readonly static ConcurrentDictionary _cachedInfos - = new ConcurrentDictionary(); - - public string LocalValueName { get; } - public ICascadingValueComponent ValueSupplier { get; } - - public CascadingParameterState(string localValueName, ICascadingValueComponent valueSupplier) - { - LocalValueName = localValueName; - ValueSupplier = valueSupplier; - } - - public static IReadOnlyList FindCascadingParameters(ComponentState componentState) - { - var componentType = componentState.Component.GetType(); - var infos = GetReflectedCascadingParameterInfos(componentType); - - // For components known not to have any cascading parameters, bail out early - if (infos == null) - { - return null; - } - - // Now try to find matches for each of the cascading parameters - // Defer instantiation of the result list until we know there's at least one - List resultStates = null; - - var numInfos = infos.Length; - for (var infoIndex = 0; infoIndex < numInfos; infoIndex++) - { - ref var info = ref infos[infoIndex]; - var supplier = GetMatchingCascadingValueSupplier(info, componentState); - if (supplier != null) - { - if (resultStates == null) - { - // Although not all parameters might be matched, we know the maximum number - resultStates = new List(infos.Length - infoIndex); - } - - resultStates.Add(new CascadingParameterState(info.ConsumerValueName, supplier)); - } - } - - return resultStates; - } - - private static ICascadingValueComponent GetMatchingCascadingValueSupplier(in ReflectedCascadingParameterInfo info, ComponentState componentState) - { - do - { - if (componentState.Component is ICascadingValueComponent candidateSupplier - && candidateSupplier.CanSupplyValue(info.ValueType, info.SupplierValueName)) - { - return candidateSupplier; - } - - componentState = componentState.ParentComponentState; - } while (componentState != null); - - // No match - return null; - } - - private static ReflectedCascadingParameterInfo[] GetReflectedCascadingParameterInfos(Type componentType) - { - if (!_cachedInfos.TryGetValue(componentType, out var infos)) - { - infos = CreateReflectedCascadingParameterInfos(componentType); - _cachedInfos[componentType] = infos; - } - - return infos; - } - - private static ReflectedCascadingParameterInfo[] CreateReflectedCascadingParameterInfos(Type componentType) - { - List result = null; - var candidateProps = ComponentProperties.GetCandidateBindableProperties(componentType); - foreach (var prop in candidateProps) - { - var attribute = prop.GetCustomAttribute(); - if (attribute != null) - { - if (result == null) - { - result = new List(); - } - - result.Add(new ReflectedCascadingParameterInfo( - prop.Name, - prop.PropertyType, - attribute.Name)); - } - } - - return result?.ToArray(); - } - - readonly struct ReflectedCascadingParameterInfo - { - public string ConsumerValueName { get; } - public string SupplierValueName { get; } - public Type ValueType { get; } - - public ReflectedCascadingParameterInfo( - string consumerValueName, Type valueType, string supplierValueName) - { - ConsumerValueName = consumerValueName; - SupplierValueName = supplierValueName; - ValueType = valueType; - } - } - } -} diff --git a/src/Components/Components/src/CascadingValue.cs b/src/Components/Components/src/CascadingValue.cs deleted file mode 100644 index db03b3d4161f..000000000000 --- a/src/Components/Components/src/CascadingValue.cs +++ /dev/null @@ -1,184 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// A component that provides a cascading value to all descendant components. - /// - public class CascadingValue : ICascadingValueComponent, IComponent - { - private RenderHandle _renderHandle; - private HashSet _subscribers; // Lazily instantiated - private bool _hasSetParametersPreviously; - - /// - /// The content to which the value should be provided. - /// - [Parameter] public RenderFragment ChildContent { get; set; } - - /// - /// The value to be provided. - /// - [Parameter] public TValue Value { get; set; } - - /// - /// Optionally gives a name to the provided value. Descendant components - /// will be able to receive the value by specifying this name. - /// - /// If no name is specified, then descendant components will receive the - /// value based the type of value they are requesting. - /// - [Parameter] public string Name { get; set; } - - /// - /// If true, indicates that will not change. This is a - /// performance optimization that allows the framework to skip setting up - /// change notifications. Set this flag only if you will not change - /// during the component's lifetime. - /// - [Parameter] public bool IsFixed { get; set; } - - object ICascadingValueComponent.CurrentValue => Value; - - bool ICascadingValueComponent.CurrentValueIsFixed => IsFixed; - - /// - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - /// - public Task SetParametersAsync(ParameterView parameters) - { - // Implementing the parameter binding manually, instead of just calling - // parameters.SetParameterProperties(this), is just a very slight perf optimization - // and makes it simpler impose rules about the params being required or not. - - var hasSuppliedValue = false; - var previousValue = Value; - var previousFixed = IsFixed; - Value = default; - ChildContent = null; - Name = null; - IsFixed = false; - - foreach (var parameter in parameters) - { - if (parameter.Name.Equals(nameof(Value), StringComparison.OrdinalIgnoreCase)) - { - Value = (TValue)parameter.Value; - hasSuppliedValue = true; - } - else if (parameter.Name.Equals(nameof(ChildContent), StringComparison.OrdinalIgnoreCase)) - { - ChildContent = (RenderFragment)parameter.Value; - } - else if (parameter.Name.Equals(nameof(Name), StringComparison.OrdinalIgnoreCase)) - { - Name = (string)parameter.Value; - if (string.IsNullOrEmpty(Name)) - { - throw new ArgumentException($"The parameter '{nameof(Name)}' for component '{nameof(CascadingValue)}' does not allow null or empty values."); - } - } - else if (parameter.Name.Equals(nameof(IsFixed), StringComparison.OrdinalIgnoreCase)) - { - IsFixed = (bool)parameter.Value; - } - else - { - throw new ArgumentException($"The component '{nameof(CascadingValue)}' does not accept a parameter with the name '{parameter.Name}'."); - } - } - - if (_hasSetParametersPreviously && IsFixed != previousFixed) - { - throw new InvalidOperationException($"The value of {nameof(IsFixed)} cannot be changed dynamically."); - } - - _hasSetParametersPreviously = true; - - // It's OK for the value to be null, but some "Value" param must be suppled - // because it serves no useful purpose to have a otherwise. - if (!hasSuppliedValue) - { - throw new ArgumentException($"Missing required parameter '{nameof(Value)}' for component '{GetType().Name}'."); - } - - // Rendering is most efficient when things are queued from rootmost to leafmost. - // Given a components A (parent) -> B (child), you want them to be queued in order - // [A, B] because if you had [B, A], then the render for A might change B's params - // making it render again, so you'd render [B, A, B], which is wasteful. - // At some point we might consider making the render queue actually enforce this - // ordering during insertion. - // - // For the CascadingValue component, this observation is why it's important to render - // ourself before notifying subscribers (which can be grandchildren or deeper). - // If we rerendered subscribers first, then our own subsequent render might cause an - // further update that makes those nested subscribers get rendered twice. - _renderHandle.Render(Render); - - if (_subscribers != null && ChangeDetection.MayHaveChanged(previousValue, Value)) - { - NotifySubscribers(parameters.Lifetime); - } - - return Task.CompletedTask; - } - - bool ICascadingValueComponent.CanSupplyValue(Type requestedType, string requestedName) - { - if (!requestedType.IsAssignableFrom(typeof(TValue))) - { - return false; - } - - return (requestedName == null && Name == null) // Match on type alone - || string.Equals(requestedName, Name, StringComparison.OrdinalIgnoreCase); // Also match on name - } - - void ICascadingValueComponent.Subscribe(ComponentState subscriber) - { -#if DEBUG - if (IsFixed) - { - // Should not be possible. User code cannot trigger this. - // Checking only to catch possible future framework bugs. - throw new InvalidOperationException($"Cannot subscribe to a {typeof(CascadingValue<>).Name} when {nameof(IsFixed)} is true."); - } -#endif - - if (_subscribers == null) - { - _subscribers = new HashSet(); - } - - _subscribers.Add(subscriber); - } - - void ICascadingValueComponent.Unsubscribe(ComponentState subscriber) - { - _subscribers.Remove(subscriber); - } - - private void NotifySubscribers(in ParameterViewLifetime lifetime) - { - foreach (var subscriber in _subscribers) - { - subscriber.NotifyCascadingValueChanged(lifetime); - } - } - - private void Render(RenderTreeBuilder builder) - { - builder.AddContent(0, ChildContent); - } - } -} diff --git a/src/Components/Components/src/ChangeDetection.cs b/src/Components/Components/src/ChangeDetection.cs deleted file mode 100644 index 9a0a1620beb4..000000000000 --- a/src/Components/Components/src/ChangeDetection.cs +++ /dev/null @@ -1,46 +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; - -namespace Microsoft.AspNetCore.Components -{ - internal class ChangeDetection - { - public static bool MayHaveChanged(T1 oldValue, T2 newValue) - { - var oldIsNotNull = oldValue != null; - var newIsNotNull = newValue != null; - if (oldIsNotNull != newIsNotNull) - { - return true; // One's null and the other isn't, so different - } - else if (oldIsNotNull) // i.e., both are not null (considering previous check) - { - var oldValueType = oldValue.GetType(); - var newValueType = newValue.GetType(); - if (oldValueType != newValueType // Definitely different - || !IsKnownImmutableType(oldValueType) // Maybe different - || !oldValue.Equals(newValue)) // Somebody says they are different - { - return true; - } - } - - // By now we know either both are null, or they are the same immutable type - // and ThatType::Equals says the two values are equal. - return false; - } - - // The contents of this list need to trade off false negatives against computation - // time. So we don't want a huge list of types to check (or would have to move to - // a hashtable lookup, which is differently expensive). It's better not to include - // uncommon types here even if they are known to be immutable. - private static bool IsKnownImmutableType(Type type) - => type.IsPrimitive - || type == typeof(string) - || type == typeof(DateTime) - || type == typeof(Type) - || type == typeof(decimal); - } -} diff --git a/src/Components/Components/src/ChangeEventArgs.cs b/src/Components/Components/src/ChangeEventArgs.cs deleted file mode 100644 index e64e4c10c723..000000000000 --- a/src/Components/Components/src/ChangeEventArgs.cs +++ /dev/null @@ -1,19 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Supplies information about an change event that is being raised. - /// - public class ChangeEventArgs : EventArgs - { - /// - /// Gets or sets the new value. - /// - public object Value { get; set; } - - } -} diff --git a/src/Components/Components/src/CompilerServices/RuntimeHelpers.cs b/src/Components/Components/src/CompilerServices/RuntimeHelpers.cs deleted file mode 100644 index 5d3469e622e8..000000000000 --- a/src/Components/Components/src/CompilerServices/RuntimeHelpers.cs +++ /dev/null @@ -1,56 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.CompilerServices -{ - /// - /// Used by generated code produced by the Components code generator. Not intended or supported - /// for use in application code. - /// - public static class RuntimeHelpers - { - /// - /// Not intended for use by application code. - /// - /// - /// - /// - public static T TypeCheck(T value) => value; - - /// - /// Not intended for use by application code. - /// - /// - /// - /// - /// - // - // This method is used with `@bind-Value` for components. When a component has a generic type, it's - // really messy to write to try and write the parameter type for ValueChanged - because it can contain generic - // type parameters. We're using a trick of type inference to generate the proper typing for the delegate - // so that method-group-to-delegate conversion works. - public static EventCallback CreateInferredEventCallback(object receiver, Action callback, T value) - { - return EventCallback.Factory.Create(receiver, callback); - } - - /// - /// Not intended for use by application code. - /// - /// - /// - /// - /// - // - // This method is used with `@bind-Value` for components. When a component has a generic type, it's - // really messy to write to try and write the parameter type for ValueChanged - because it can contain generic - // type parameters. We're using a trick of type inference to generate the proper typing for the delegate - // so that method-group-to-delegate conversion works. - public static EventCallback CreateInferredEventCallback(object receiver, Func callback, T value) - { - return EventCallback.Factory.Create(receiver, callback); - } - } -} diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs deleted file mode 100644 index 51c95f386b1f..000000000000 --- a/src/Components/Components/src/ComponentBase.cs +++ /dev/null @@ -1,336 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components -{ - // IMPORTANT - // - // Many of these names are used in code generation. Keep these in sync with the code generation code - // See: src/Microsoft.AspNetCore.Components.Razor.Extensions/ComponentsApi.cs - - // Most of the developer-facing component lifecycle concepts are encapsulated in this - // base class. The core components rendering system doesn't know about them (it only knows - // about IComponent). This gives us flexibility to change the lifecycle concepts easily, - // or for developers to design their own lifecycles as different base classes. - - // TODO: When the component lifecycle design stabilises, add proper unit tests for ComponentBase. - - /// - /// Optional base class for components. Alternatively, components may - /// implement directly. - /// - public abstract class ComponentBase : IComponent, IHandleEvent, IHandleAfterRender - { - private readonly RenderFragment _renderFragment; - private RenderHandle _renderHandle; - private bool _initialized; - private bool _hasNeverRendered = true; - private bool _hasPendingQueuedRender; - private bool _hasCalledOnAfterRender; - - /// - /// Constructs an instance of . - /// - public ComponentBase() - { - _renderFragment = builder => - { - _hasPendingQueuedRender = false; - _hasNeverRendered = false; - BuildRenderTree(builder); - }; - } - - /// - /// Renders the component to the supplied . - /// - /// A that will receive the render output. - protected virtual void BuildRenderTree(RenderTreeBuilder builder) - { - // Developers can either override this method in derived classes, or can use Razor - // syntax to define a derived class and have the compiler generate the method. - - // Other code within this class should *not* invoke BuildRenderTree directly, - // but instead should invoke the _renderFragment field. - } - - /// - /// Method invoked when the component is ready to start, having received its - /// initial parameters from its parent in the render tree. - /// - protected virtual void OnInitialized() - { - } - - /// - /// Method invoked when the component is ready to start, having received its - /// initial parameters from its parent in the render tree. - /// - /// Override this method if you will perform an asynchronous operation and - /// want the component to refresh when that operation is completed. - /// - /// A representing any asynchronous operation. - protected virtual Task OnInitializedAsync() - => Task.CompletedTask; - - /// - /// Method invoked when the component has received parameters from its parent in - /// the render tree, and the incoming values have been assigned to properties. - /// - protected virtual void OnParametersSet() - { - } - - /// - /// Method invoked when the component has received parameters from its parent in - /// the render tree, and the incoming values have been assigned to properties. - /// - /// A representing any asynchronous operation. - protected virtual Task OnParametersSetAsync() - => Task.CompletedTask; - - /// - /// Notifies the component that its state has changed. When applicable, this will - /// cause the component to be re-rendered. - /// - protected void StateHasChanged() - { - if (_hasPendingQueuedRender) - { - return; - } - - if (_hasNeverRendered || ShouldRender()) - { - _hasPendingQueuedRender = true; - - try - { - _renderHandle.Render(_renderFragment); - } - catch - { - _hasPendingQueuedRender = false; - throw; - } - } - } - - /// - /// Returns a flag to indicate whether the component should render. - /// - /// - protected virtual bool ShouldRender() - => true; - - /// - /// Method invoked after each time the component has been rendered. - /// - /// - /// Set to true if this is the first time has been invoked - /// on this component instance; otherwise false. - /// - /// - /// The and lifecycle methods - /// are useful for performing interop, or interacting with values recieved from @ref. - /// Use the parameter to ensure that initialization work is only performed - /// once. - /// - protected virtual void OnAfterRender(bool firstRender) - { - } - - /// - /// Method invoked after each time the component has been rendered. Note that the component does - /// not automatically re-render after the completion of any returned , because - /// that would cause an infinite render loop. - /// - /// - /// Set to true if this is the first time has been invoked - /// on this component instance; otherwise false. - /// - /// A representing any asynchronous operation. - /// - /// The and lifecycle methods - /// are useful for performing interop, or interacting with values recieved from @ref. - /// Use the parameter to ensure that initialization work is only performed - /// once. - /// - protected virtual Task OnAfterRenderAsync(bool firstRender) - => Task.CompletedTask; - - /// - /// Executes the supplied work item on the associated renderer's - /// synchronization context. - /// - /// The work item to execute. - protected Task InvokeAsync(Action workItem) - => _renderHandle.Dispatcher.InvokeAsync(workItem); - - /// - /// Executes the supplied work item on the associated renderer's - /// synchronization context. - /// - /// The work item to execute. - protected Task InvokeAsync(Func workItem) - => _renderHandle.Dispatcher.InvokeAsync(workItem); - - void IComponent.Attach(RenderHandle renderHandle) - { - // This implicitly means a ComponentBase can only be associated with a single - // renderer. That's the only use case we have right now. If there was ever a need, - // a component could hold a collection of render handles. - if (_renderHandle.IsInitialized) - { - throw new InvalidOperationException($"The render handle is already set. Cannot initialize a {nameof(ComponentBase)} more than once."); - } - - _renderHandle = renderHandle; - } - - - /// - /// Sets parameters supplied by the component's parent in the render tree. - /// - /// The parameters. - /// A that completes when the component has finished updating and rendering itself. - /// - /// - /// The method should be passed the entire set of parameter values each - /// time is called. It not required that the caller supply a parameter - /// value for all parameters that are logically understood by the component. - /// - /// - /// The default implementation of will set the value of each property - /// decorated with or that has - /// a corresponding value in the . Parameters that do not have a corresponding value - /// will be unchanged. - /// - /// - public virtual Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - if (!_initialized) - { - _initialized = true; - - return RunInitAndSetParametersAsync(); - } - else - { - return CallOnParametersSetAsync(); - } - } - - private async Task RunInitAndSetParametersAsync() - { - OnInitialized(); - var task = OnInitializedAsync(); - - if (task.Status != TaskStatus.RanToCompletion && task.Status != TaskStatus.Canceled) - { - // Call state has changed here so that we render after the sync part of OnInitAsync has run - // and wait for it to finish before we continue. If no async work has been done yet, we want - // to defer calling StateHasChanged up until the first bit of async code happens or until - // the end. Additionally, we want to avoid calling StateHasChanged if no - // async work is to be performed. - StateHasChanged(); - - try - { - await task; - } - catch // avoiding exception filters for AOT runtime support - { - // Ignore exceptions from task cancelletions. - // Awaiting a canceled task may produce either an OperationCanceledException (if produced as a consequence of - // CancellationToken.ThrowIfCancellationRequested()) or a TaskCanceledException (produced as a consequence of awaiting Task.FromCanceled). - // It's much easier to check the state of the Task (i.e. Task.IsCanceled) rather than catch two distinct exceptions. - if (!task.IsCanceled) - { - throw; - } - } - - // Don't call StateHasChanged here. CallOnParametersSetAsync should handle that for us. - } - - await CallOnParametersSetAsync(); - } - - private Task CallOnParametersSetAsync() - { - OnParametersSet(); - var task = OnParametersSetAsync(); - // If no async work is to be performed, i.e. the task has already ran to completion - // or was canceled by the time we got to inspect it, avoid going async and re-invoking - // StateHasChanged at the culmination of the async work. - var shouldAwaitTask = task.Status != TaskStatus.RanToCompletion && - task.Status != TaskStatus.Canceled; - - // We always call StateHasChanged here as we want to trigger a rerender after OnParametersSet and - // the synchronous part of OnParametersSetAsync has run. - StateHasChanged(); - - return shouldAwaitTask ? - CallStateHasChangedOnAsyncCompletion(task) : - Task.CompletedTask; - } - - private async Task CallStateHasChangedOnAsyncCompletion(Task task) - { - try - { - await task; - } - catch // avoiding exception filters for AOT runtime support - { - // Ignore exceptions from task cancelletions, but don't bother issuing a state change. - if (task.IsCanceled) - { - return; - } - - throw; - } - - StateHasChanged(); - } - - Task IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, object arg) - { - var task = callback.InvokeAsync(arg); - var shouldAwaitTask = task.Status != TaskStatus.RanToCompletion && - task.Status != TaskStatus.Canceled; - - // After each event, we synchronously re-render (unless !ShouldRender()) - // This just saves the developer the trouble of putting "StateHasChanged();" - // at the end of every event callback. - StateHasChanged(); - - return shouldAwaitTask ? - CallStateHasChangedOnAsyncCompletion(task) : - Task.CompletedTask; - } - - Task IHandleAfterRender.OnAfterRenderAsync() - { - var firstRender = !_hasCalledOnAfterRender; - _hasCalledOnAfterRender |= true; - - OnAfterRender(firstRender); - - return OnAfterRenderAsync(firstRender); - - // Note that we don't call StateHasChanged to trigger a render after - // handling this, because that would be an infinite loop. The only - // reason we have OnAfterRenderAsync is so that the developer doesn't - // have to use "async void" and do their own exception handling in - // the case where they want to start an async task. - } - } -} diff --git a/src/Components/Components/src/ComponentFactory.cs b/src/Components/Components/src/ComponentFactory.cs deleted file mode 100644 index bf5de30d2a5d..000000000000 --- a/src/Components/Components/src/ComponentFactory.cs +++ /dev/null @@ -1,88 +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.Concurrent; -using System.Linq; -using System.Reflection; -using Microsoft.AspNetCore.Components.Reflection; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// The property on this type is used as a static global cache. Ensure any changes to this type - /// are thread safe and can be safely cached statically. - /// - internal class ComponentFactory - { - private static readonly BindingFlags _injectablePropertyBindingFlags - = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - - private readonly ConcurrentDictionary> _cachedInitializers - = new ConcurrentDictionary>(); - - public static readonly ComponentFactory Instance = new ComponentFactory(); - - public IComponent InstantiateComponent(IServiceProvider serviceProvider, Type componentType) - { - var instance = Activator.CreateInstance(componentType); - if (!(instance is IComponent component)) - { - throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType)); - } - - PerformPropertyInjection(serviceProvider, component); - return component; - } - - private void PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance) - { - // This is thread-safe because _cachedInitializers is a ConcurrentDictionary. - // We might generate the initializer more than once for a given type, but would - // still produce the correct result. - var instanceType = instance.GetType(); - if (!_cachedInitializers.TryGetValue(instanceType, out var initializer)) - { - initializer = CreateInitializer(instanceType); - _cachedInitializers.TryAdd(instanceType, initializer); - } - - initializer(serviceProvider, instance); - } - - private Action CreateInitializer(Type type) - { - // Do all the reflection up front - var injectableProperties = - MemberAssignment.GetPropertiesIncludingInherited(type, _injectablePropertyBindingFlags) - .Where(p => p.IsDefined(typeof(InjectAttribute))); - - var injectables = injectableProperties.Select(property => - ( - propertyName: property.Name, - propertyType: property.PropertyType, - setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false) - )).ToArray(); - - return Initialize; - - // Return an action whose closure can write all the injected properties - // without any further reflection calls (just typecasts) - void Initialize(IServiceProvider serviceProvider, IComponent component) - { - foreach (var (propertyName, propertyType, setter) in injectables) - { - var serviceInstance = serviceProvider.GetService(propertyType); - if (serviceInstance == null) - { - throw new InvalidOperationException($"Cannot provide a value for property " + - $"'{propertyName}' on type '{type.FullName}'. There is no " + - $"registered service of type '{propertyType}'."); - } - - setter.SetValue(component, serviceInstance); - } - } - } - } -} diff --git a/src/Components/Components/src/Dispatcher.cs b/src/Components/Components/src/Dispatcher.cs deleted file mode 100644 index 88ba02081385..000000000000 --- a/src/Components/Components/src/Dispatcher.cs +++ /dev/null @@ -1,90 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Dispatches external actions to be executed on the context of a . - /// - public abstract class Dispatcher - { - /// - /// Creates a default instance of . - /// - /// A instance. - public static Dispatcher CreateDefault() => new RendererSynchronizationContextDispatcher(); - - /// - /// Provides notifications of unhandled exceptions that occur within the dispatcher. - /// - internal event UnhandledExceptionEventHandler UnhandledException; - - /// - /// Validates that the currently executing code is running inside the dispatcher. - /// - public void AssertAccess() - { - if (!CheckAccess()) - { - throw new InvalidOperationException( - "The current thread is not associated with the Dispatcher. " + - "Use InvokeAsync() to switch execution to the Dispatcher when " + - "triggering rendering or component state."); - } - } - - /// - /// Returns a value that determines whether using the dispatcher to invoke a work item is required - /// from the current context. - /// - /// true if invoking is required, otherwise false. - public abstract bool CheckAccess(); - - /// - /// Invokes the given in the context of the associated . - /// - /// The action to execute. - /// A that will be completed when the action has finished executing. - public abstract Task InvokeAsync(Action workItem); - - /// - /// Invokes the given in the context of the associated . - /// - /// The asynchronous action to execute. - /// A that will be completed when the action has finished executing. - public abstract Task InvokeAsync(Func workItem); - - /// - /// Invokes the given in the context of the associated . - /// - /// The function to execute. - /// A that will be completed when the function has finished executing. - public abstract Task InvokeAsync(Func workItem); - - /// - /// Invokes the given in the context of the associated . - /// - /// The asynchronous function to execute. - /// A that will be completed when the function has finished executing. - public abstract Task InvokeAsync(Func> workItem); - - /// - /// Called to notify listeners of an unhandled exception. - /// - /// The . - protected void OnUnhandledException(UnhandledExceptionEventArgs e) - { - if (e is null) - { - throw new ArgumentNullException(nameof(e)); - } - - UnhandledException?.Invoke(this, e); - } - } -} diff --git a/src/Components/Components/src/ElementReference.cs b/src/Components/Components/src/ElementReference.cs deleted file mode 100644 index e25c673be79b..000000000000 --- a/src/Components/Components/src/ElementReference.cs +++ /dev/null @@ -1,55 +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.Globalization; -using System.Threading; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Represents a reference to a rendered element. - /// - public readonly struct ElementReference - { - private static long _nextIdForWebAssemblyOnly = 1; - - /// - /// Gets a unique identifier for . - /// - /// - /// The Id is unique at least within the scope of a given user/circuit. - /// This property is public to support Json serialization and should not be used by user code. - /// - public string Id { get; } - - public ElementReference(string id) - { - Id = id; - } - - internal static ElementReference CreateWithUniqueId() - => new ElementReference(CreateUniqueId()); - - private static string CreateUniqueId() - { - if (PlatformInfo.IsWebAssembly) - { - // On WebAssembly there's only one user, so it's fine to expose the number - // of IDs that have been assigned, and this is cheaper than creating a GUID. - // It's unfortunate that this still involves a heap allocation. If that becomes - // a problem we could extend RenderTreeFrame to have both "string" and "long" - // fields for ElementRefCaptureId, of which only one would be in use depending - // on the platform. - var id = Interlocked.Increment(ref _nextIdForWebAssemblyOnly); - return id.ToString(CultureInfo.InvariantCulture); - } - else - { - // For remote rendering, it's important not to disclose any cross-user state, - // such as the number of IDs that have been assigned. - return Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture); - } - } - } -} diff --git a/src/Components/Components/src/EventCallback.cs b/src/Components/Components/src/EventCallback.cs deleted file mode 100644 index 3ba05ceaba41..000000000000 --- a/src/Components/Components/src/EventCallback.cs +++ /dev/null @@ -1,69 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// A bound event handler delegate. - /// - public readonly struct EventCallback : IEventCallback - { - /// - /// Gets a reference to the . - /// - public static readonly EventCallbackFactory Factory = new EventCallbackFactory(); - - /// - /// Gets an empty . - /// - public static readonly EventCallback Empty = new EventCallback(null, (Action)(() => { })); - - internal readonly MulticastDelegate Delegate; - internal readonly IHandleEvent Receiver; - - /// - /// Creates the new . - /// - /// The event receiver. - /// The delegate to bind. - public EventCallback(IHandleEvent receiver, MulticastDelegate @delegate) - { - Receiver = receiver; - Delegate = @delegate; - } - - /// - /// Gets a value that indicates whether the delegate associated with this event dispatcher is non-null. - /// - public bool HasDelegate => Delegate != null; - - // This is a hint to the runtime that Receiver is a different object than what - // Delegate.Target points to. This allows us to avoid boxing the command object - // when building the render tree. See logic where this is used. - internal bool RequiresExplicitReceiver => Receiver != null && !object.ReferenceEquals(Receiver, Delegate?.Target); - - /// - /// Invokes the delegate associated with this binding and dispatches an event notification to the - /// appropriate component. - /// - /// The argument. - /// A which completes asynchronously once event processing has completed. - public Task InvokeAsync(object arg) - { - if (Receiver == null) - { - return EventCallbackWorkItem.InvokeAsync(Delegate, arg); - } - - return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); - } - - object IEventCallback.UnpackForRenderTree() - { - return RequiresExplicitReceiver ? (object)this : Delegate; - } - } -} diff --git a/src/Components/Components/src/EventCallbackFactory.cs b/src/Components/Components/src/EventCallbackFactory.cs deleted file mode 100644 index 1b53376b85ae..000000000000 --- a/src/Components/Components/src/EventCallbackFactory.cs +++ /dev/null @@ -1,241 +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.ComponentModel; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// A factory for creating and - /// instances. - /// - public sealed class EventCallbackFactory - { - /// - /// Returns the provided . For internal framework use only. - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback Create(object receiver, EventCallback callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return callback; - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Action callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Action callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Func callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Func callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Returns the provided . For internal framework use only. - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback Create(object receiver, EventCallback callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return new EventCallback(callback.Receiver, callback.Delegate); - } - - /// - /// Returns the provided . For internal framework use only. - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback Create(object receiver, EventCallback callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return callback; - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Action callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Action callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Func callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The event receiver. - /// The event callback. - /// The . - public EventCallback Create(object receiver, Func callback) - { - if (receiver == null) - { - throw new ArgumentNullException(nameof(receiver)); - } - - return CreateCore(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . For internal framework use only. - /// - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback CreateInferred(object receiver, Action callback, TValue value) - { - return Create(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . For internal framework use only. - /// - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback CreateInferred(object receiver, Func callback, TValue value) - { - return Create(receiver, callback); - } - - private EventCallback CreateCore(object receiver, MulticastDelegate callback) - { - return new EventCallback(callback?.Target as IHandleEvent ?? receiver as IHandleEvent, callback); - } - - private EventCallback CreateCore(object receiver, MulticastDelegate callback) - { - return new EventCallback(callback?.Target as IHandleEvent ?? receiver as IHandleEvent, callback); - } - } -} diff --git a/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs b/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs deleted file mode 100644 index 99eac1965a06..000000000000 --- a/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs +++ /dev/null @@ -1,539 +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.Globalization; -using static Microsoft.AspNetCore.Components.BindConverter; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Contains extension methods for two-way binding using . For internal use only. - /// - // - // NOTE: for number parsing, the HTML5 spec dictates that the DOM will represent - // number values as floating point numbers using `.` as the period separator. This is NOT culture senstive. - // Put another way, the user might see `,` as their decimal separator, but the value available in events - // to JS code is always simpilar to what .NET parses with InvariantCulture. - // - // See: https://www.w3.org/TR/html5/sec-forms.html#number-state-typenumber - // See: https://www.w3.org/TR/html5/infrastructure.html#valid-floating-point-number - // - // For now we're not necessarily handling this correctly since we parse the same way for number and text. - public static class EventCallbackFactoryBinderExtensions - { - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - string existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToString); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - bool existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToBool); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - bool? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableBool); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - int existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToInt); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - int? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableInt); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - long existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToLong); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - long? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableLong); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - float existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToFloat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - float? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableFloat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - double existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToDoubleDelegate); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - double? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableDoubleDelegate); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - decimal existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToDecimal); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - decimal? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableDecimal); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTime existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToDateTime); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTime existingValue, - string format, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, format, ConvertToDateTimeWithFormat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTime? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableDateTime); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTime? existingValue, - string format, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, format, ConvertToNullableDateTimeWithFormat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTimeOffset existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToDateTimeOffset); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTimeOffset existingValue, - string format, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, format, ConvertToDateTimeOffsetWithFormat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTimeOffset? existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ConvertToNullableDateTimeOffset); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - DateTimeOffset? existingValue, - string format, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, format, ConvertToNullableDateTimeOffsetWithFormat); - } - - /// - /// For internal use only. - /// - /// - /// - /// - /// - /// - /// - /// - public static EventCallback CreateBinder( - this EventCallbackFactory factory, - object receiver, - Action setter, - T existingValue, - CultureInfo culture = null) - { - return CreateBinderCore(factory, receiver, setter, culture, ParserDelegateCache.Get()); - } - - private static EventCallback CreateBinderCore( - this EventCallbackFactory factory, - object receiver, - Action setter, - CultureInfo culture, - BindConverter.BindParser converter) - { - Action callback = e => - { - T value = default; - var converted = false; - try - { - converted = converter(e.Value, culture, out value); - } - catch - { - } - - // We only invoke the setter if the conversion didn't throw, or if the newly-entered value is empty. - // If the user entered some non-empty value we couldn't parse, we leave the state of the .NET field - // unchanged, which for a two-way binding results in the UI reverting to its previous valid state - // because the diff will see the current .NET output no longer matches the render tree since we - // patched it to reflect the state of the UI. - // - // This reversion behavior is valuable because alternatives are problematic: - // - If we assigned default(T) on failure, the user would lose whatever data they were editing, - // for example if they accidentally pressed an alphabetical key while editing a number with - // @bind:event="oninput" - // - If the diff mechanism didn't revert to the previous good value, the user wouldn't necessarily - // know that the data they are submitting is different from what they think they've typed - if (converted) - { - setter(value); - } - else if (string.Empty.Equals(e.Value)) - { - setter(default); - } - }; - return factory.Create(receiver, callback); - } - - private static EventCallback CreateBinderCore( - this EventCallbackFactory factory, - object receiver, - Action setter, - CultureInfo culture, - string format, - BindConverter.BindParserWithFormat converter) - { - Action callback = e => - { - T value = default; - var converted = false; - try - { - converted = converter(e.Value, culture, format, out value); - } - catch - { - } - - // We only invoke the setter if the conversion didn't throw, or if the newly-entered value is empty. - // If the user entered some non-empty value we couldn't parse, we leave the state of the .NET field - // unchanged, which for a two-way binding results in the UI reverting to its previous valid state - // because the diff will see the current .NET output no longer matches the render tree since we - // patched it to reflect the state of the UI. - // - // This reversion behavior is valuable because alternatives are problematic: - // - If we assigned default(T) on failure, the user would lose whatever data they were editing, - // for example if they accidentally pressed an alphabetical key while editing a number with - // @bind:event="oninput" - // - If the diff mechanism didn't revert to the previous good value, the user wouldn't necessarily - // know that the data they are submitting is different from what they think they've typed - if (converted) - { - setter(value); - } - else if (string.Empty.Equals(e.Value)) - { - setter(default); - } - }; - return factory.Create(receiver, callback); - } - } -} diff --git a/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs b/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs deleted file mode 100644 index d0c4aec3038f..000000000000 --- a/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs +++ /dev/null @@ -1,86 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Provides extension methods for and types. - /// - public static class EventCallbackFactoryEventArgsExtensions - { - /// - /// Creates an for the provided and - /// . - /// - /// The . - /// The event receiver. - /// The event callback. - /// The . - public static EventCallback Create(this EventCallbackFactory factory, object receiver, Action callback) - { - if (factory == null) - { - throw new ArgumentNullException(nameof(factory)); - } - - return factory.Create(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The . - /// The event receiver. - /// The event callback. - /// The . - public static EventCallback Create(this EventCallbackFactory factory, object receiver, Func callback) - { - if (factory == null) - { - throw new ArgumentNullException(nameof(factory)); - } - - return factory.Create(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The . - /// The event receiver. - /// The event callback. - /// The . - public static EventCallback Create(this EventCallbackFactory factory, object receiver, Action callback) - { - if (factory == null) - { - throw new ArgumentNullException(nameof(factory)); - } - - return factory.Create(receiver, callback); - } - - /// - /// Creates an for the provided and - /// . - /// - /// The . - /// The event receiver. - /// The event callback. - /// The . - public static EventCallback Create(this EventCallbackFactory factory, object receiver, Func callback) - { - if (factory == null) - { - throw new ArgumentNullException(nameof(factory)); - } - - return factory.Create(receiver, callback); - } - } -} diff --git a/src/Components/Components/src/EventCallbackOfT.cs b/src/Components/Components/src/EventCallbackOfT.cs deleted file mode 100644 index 918d8d62e24d..000000000000 --- a/src/Components/Components/src/EventCallbackOfT.cs +++ /dev/null @@ -1,69 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// A bound event handler delegate. - /// - public readonly struct EventCallback : IEventCallback - { - /// - /// Gets an empty . - /// - public static readonly EventCallback Empty = new EventCallback(null, (Action)(() => { })); - - internal readonly MulticastDelegate Delegate; - internal readonly IHandleEvent Receiver; - - /// - /// Creates the new . - /// - /// The event receiver. - /// The delegate to bind. - public EventCallback(IHandleEvent receiver, MulticastDelegate @delegate) - { - Receiver = receiver; - Delegate = @delegate; - } - - /// - /// Gets a value that indicates whether the delegate associated with this event dispatcher is non-null. - /// - public bool HasDelegate => Delegate != null; - - // This is a hint to the runtime that Receiver is a different object than what - // Delegate.Target points to. This allows us to avoid boxing the command object - // when building the render tree. See logic where this is used. - internal bool RequiresExplicitReceiver => Receiver != null && !object.ReferenceEquals(Receiver, Delegate?.Target); - - /// - /// Invokes the delegate associated with this binding and dispatches an event notification to the - /// appropriate component. - /// - /// The argument. - /// A which completes asynchronously once event processing has completed. - public Task InvokeAsync(TValue arg) - { - if (Receiver == null) - { - return EventCallbackWorkItem.InvokeAsync(Delegate, arg); - } - - return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); - } - - internal EventCallback AsUntyped() - { - return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate); - } - - object IEventCallback.UnpackForRenderTree() - { - return RequiresExplicitReceiver ? (object)AsUntyped() : Delegate; - } - } -} diff --git a/src/Components/Components/src/EventCallbackWorkItem.cs b/src/Components/Components/src/EventCallbackWorkItem.cs deleted file mode 100644 index bb7c8320b296..000000000000 --- a/src/Components/Components/src/EventCallbackWorkItem.cs +++ /dev/null @@ -1,79 +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.Reflection; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Wraps a callback delegate associated with an event. - /// - public readonly struct EventCallbackWorkItem - { - /// - /// An empty . - /// - public static readonly EventCallbackWorkItem Empty = new EventCallbackWorkItem(null); - - private readonly MulticastDelegate _delegate; - - /// - /// Creates a new with the provided . - /// - /// The callback delegate. - public EventCallbackWorkItem(MulticastDelegate @delegate) - { - _delegate = @delegate; - } - - /// - /// Invokes the delegate associated with this . - /// - /// The argument to provide to the delegate. May be null. - /// A then will complete asynchronously once the delegate has completed. - public Task InvokeAsync(object arg) - { - return InvokeAsync(_delegate, arg); - } - - internal static Task InvokeAsync(MulticastDelegate @delegate, T arg) - { - switch (@delegate) - { - case null: - return Task.CompletedTask; - - case Action action: - action.Invoke(); - return Task.CompletedTask; - - case Action actionEventArgs: - actionEventArgs.Invoke(arg); - return Task.CompletedTask; - - case Func func: - return func.Invoke(); - - case Func funcEventArgs: - return funcEventArgs.Invoke(arg); - - default: - { - try - { - return @delegate.DynamicInvoke(arg) as Task ?? Task.CompletedTask; - } - catch (TargetInvocationException e) - { - // Since we fell into the DynamicInvoke case, any exception will be wrapped - // in a TIE. We can expect this to be thrown synchronously, so it's low overhead - // to unwrap it. - return Task.FromException(e.InnerException); - } - } - } - } - } -} diff --git a/src/Components/Components/src/EventHandlerAttribute.cs b/src/Components/Components/src/EventHandlerAttribute.cs deleted file mode 100644 index 67307fb9efe5..000000000000 --- a/src/Components/Components/src/EventHandlerAttribute.cs +++ /dev/null @@ -1,68 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Associates an event argument type with an event attribute name. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] - public sealed class EventHandlerAttribute : Attribute - { - /// - /// Constructs an instance of . - /// - /// - /// - public EventHandlerAttribute(string attributeName, Type eventArgsType) : this(attributeName, eventArgsType, false, false) - { - } - - /// - /// Constructs an instance of . - /// - /// - /// - /// - /// - public EventHandlerAttribute(string attributeName, Type eventArgsType, bool enableStopPropagation, bool enablePreventDefault) - { - if (attributeName == null) - { - throw new ArgumentNullException(nameof(attributeName)); - } - - if (eventArgsType == null) - { - throw new ArgumentNullException(nameof(eventArgsType)); - } - - AttributeName = attributeName; - EventArgsType = eventArgsType; - EnableStopPropagation = enableStopPropagation; - EnablePreventDefault = enablePreventDefault; - } - - /// - /// Gets the attribute name. - /// - public string AttributeName { get; } - - /// - /// Gets the event argument type. - /// - public Type EventArgsType { get; } - - /// - /// Gets the event's ability to stop propagation. - /// - public bool EnableStopPropagation { get; } - - /// - /// Gets the event's ability to prevent default event flow. - /// - public bool EnablePreventDefault { get; } - } -} diff --git a/src/Components/Components/src/ICascadingValueComponent.cs b/src/Components/Components/src/ICascadingValueComponent.cs deleted file mode 100644 index de9da715a217..000000000000 --- a/src/Components/Components/src/ICascadingValueComponent.cs +++ /dev/null @@ -1,24 +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.Rendering; -using System; - -namespace Microsoft.AspNetCore.Components -{ - internal interface ICascadingValueComponent - { - // This interface exists only so that CascadingParameterState has a way - // to work with all CascadingValue types regardless of T. - - bool CanSupplyValue(Type valueType, string valueName); - - object CurrentValue { get; } - - bool CurrentValueIsFixed { get; } - - void Subscribe(ComponentState subscriber); - - void Unsubscribe(ComponentState subscriber); - } -} diff --git a/src/Components/Components/src/IComponent.cs b/src/Components/Components/src/IComponent.cs deleted file mode 100644 index 936cd379441a..000000000000 --- a/src/Components/Components/src/IComponent.cs +++ /dev/null @@ -1,31 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Represents a UI component. - /// - public interface IComponent - { - /// - /// Attaches the component to a . - /// - /// A that allows the component to be rendered. - void Attach(RenderHandle renderHandle); - - /// - /// Sets parameters supplied by the component's parent in the render tree. - /// - /// The parameters. - /// A that completes when the component has finished updating and rendering itself. - /// - /// The method should be passed the entire set of parameter values each - /// time is called. It not required that the caller supply a parameter - /// value for all parameters that are logically understood by the component. - /// - Task SetParametersAsync(ParameterView parameters); - } -} diff --git a/src/Components/Components/src/IEventCallback.cs b/src/Components/Components/src/IEventCallback.cs deleted file mode 100644 index 6c9fcac7a35d..000000000000 --- a/src/Components/Components/src/IEventCallback.cs +++ /dev/null @@ -1,13 +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 -{ - // Used to understand boxed generic EventCallbacks - internal interface IEventCallback - { - bool HasDelegate { get; } - - object UnpackForRenderTree(); - } -} diff --git a/src/Components/Components/src/IHandleAfterRender.cs b/src/Components/Components/src/IHandleAfterRender.cs deleted file mode 100644 index 349138519f15..000000000000 --- a/src/Components/Components/src/IHandleAfterRender.cs +++ /dev/null @@ -1,19 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Interface implemented by components that receive notification that they have been rendered. - /// - public interface IHandleAfterRender - { - /// - /// Notifies the component that it has been rendered. - /// - /// A that represents the asynchronous event handling operation. - Task OnAfterRenderAsync(); - } -} diff --git a/src/Components/Components/src/IHandleEvent.cs b/src/Components/Components/src/IHandleEvent.cs deleted file mode 100644 index 478102cbe81c..000000000000 --- a/src/Components/Components/src/IHandleEvent.cs +++ /dev/null @@ -1,23 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Interface implemented by components that receive notification of state changes. - /// - public interface IHandleEvent - { - /// - /// Notifies the a state change has been triggered. - /// - /// The associated with this event. - /// The argument associated with this event. - /// - /// A that completes once the component has processed the state change. - /// - Task HandleEventAsync(EventCallbackWorkItem item, object arg); - } -} diff --git a/src/Components/Components/src/InjectAttribute.cs b/src/Components/Components/src/InjectAttribute.cs deleted file mode 100644 index f18381fe9cf3..000000000000 --- a/src/Components/Components/src/InjectAttribute.cs +++ /dev/null @@ -1,16 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Indicates that the associated property should have a value injected from the - /// service provider during initialization. - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public sealed class InjectAttribute : Attribute - { - } -} diff --git a/src/Components/Components/src/LayoutAttribute.cs b/src/Components/Components/src/LayoutAttribute.cs deleted file mode 100644 index 8e4fa7892274..000000000000 --- a/src/Components/Components/src/LayoutAttribute.cs +++ /dev/null @@ -1,40 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Indicates that the associated component type uses a specified layout. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - public sealed class LayoutAttribute : Attribute - { - /// - /// Constructs an instance of . - /// - /// The type of the layout. - public LayoutAttribute(Type layoutType) - { - LayoutType = layoutType ?? throw new ArgumentNullException(nameof(layoutType)); - - if (!typeof(IComponent).IsAssignableFrom(layoutType)) - { - throw new ArgumentException($"Invalid layout type: {layoutType.FullName} " + - $"does not implement {typeof(IComponent).FullName}."); - } - - // Note that we can't validate its acceptance of a 'Body' parameter at this stage, - // because the contract doesn't force them to be known statically. However it will - // be a runtime error if the referenced component type rejects the 'Body' parameter - // when it gets used. - } - - /// - /// The type of the layout. The type must implement - /// and must accept a parameter with the name 'Body'. - /// - public Type LayoutType { get; private set; } - } -} diff --git a/src/Components/Components/src/LayoutComponentBase.cs b/src/Components/Components/src/LayoutComponentBase.cs deleted file mode 100644 index 776b97b280f9..000000000000 --- a/src/Components/Components/src/LayoutComponentBase.cs +++ /dev/null @@ -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. - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Optional base class for components that represent a layout. - /// Alternatively, components may implement directly - /// and declare their own parameter named . - /// - public abstract class LayoutComponentBase : ComponentBase - { - internal const string BodyPropertyName = nameof(Body); - - /// - /// Gets the content to be rendered inside the layout. - /// - [Parameter] - public RenderFragment Body { get; set; } - } -} diff --git a/src/Components/Components/src/LayoutView.cs b/src/Components/Components/src/LayoutView.cs deleted file mode 100644 index 7b88d181f0e0..000000000000 --- a/src/Components/Components/src/LayoutView.cs +++ /dev/null @@ -1,77 +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.Reflection; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Displays the specified content inside the specified layout and any further - /// nested layouts. - /// - public class LayoutView : IComponent - { - private static readonly RenderFragment EmptyRenderFragment = builder => { }; - - private RenderHandle _renderHandle; - - /// - /// Gets or sets the content to display. - /// - [Parameter] - public RenderFragment ChildContent { get; set; } - - /// - /// Gets or sets the type of the layout in which to display the content. - /// The type must implement and accept a parameter named . - /// - [Parameter] - public Type Layout { get; set; } - - /// - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - /// - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - Render(); - return Task.CompletedTask; - } - - private void Render() - { - // In the middle goes the supplied content - var fragment = ChildContent ?? EmptyRenderFragment; - - // Then repeatedly wrap that in each layer of nested layout until we get - // to a layout that has no parent - var layoutType = Layout; - while (layoutType != null) - { - fragment = WrapInLayout(layoutType, fragment); - layoutType = GetParentLayoutType(layoutType); - } - - _renderHandle.Render(fragment); - } - - private static RenderFragment WrapInLayout(Type layoutType, RenderFragment bodyParam) - { - return builder => - { - builder.OpenComponent(0, layoutType); - builder.AddAttribute(1, LayoutComponentBase.BodyPropertyName, bodyParam); - builder.CloseComponent(); - }; - } - - private static Type GetParentLayoutType(Type type) - => type.GetCustomAttribute()?.LayoutType; - } -} diff --git a/src/Components/Components/src/LocationChangeException.cs b/src/Components/Components/src/LocationChangeException.cs deleted file mode 100644 index 13010eb5c156..000000000000 --- a/src/Components/Components/src/LocationChangeException.cs +++ /dev/null @@ -1,23 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// An exception thrown when throws an exception. - /// - public sealed class LocationChangeException : Exception - { - /// - /// Creates a new instance of . - /// - /// The exception message. - /// The inner exception. - public LocationChangeException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/src/Components/Components/src/MarkupString.cs b/src/Components/Components/src/MarkupString.cs deleted file mode 100644 index c0f9c8af0a0d..000000000000 --- a/src/Components/Components/src/MarkupString.cs +++ /dev/null @@ -1,36 +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 -{ - /// - /// A string value that can be rendered as markup such as HTML. - /// - public readonly struct MarkupString - { - /// - /// Constructs an instance of . - /// - /// The value for the new instance. - public MarkupString(string value) - { - Value = value; - } - - /// - /// Gets the value of the . - /// - public string Value { get; } - - /// - /// Casts a to a . - /// - /// The value. - public static explicit operator MarkupString(string value) - => new MarkupString(value); - - /// - public override string ToString() - => Value ?? string.Empty; - } -} diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj deleted file mode 100644 index 4c0a31a3f6e0..000000000000 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj +++ /dev/null @@ -1,60 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - $(DefaultNetCoreTargetFramework) - Components feature for ASP.NET Core. - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Microsoft.AspNetCore.Components.multitarget.nuspec - Microsoft.AspNetCore.Components.netcoreapp.nuspec - $(GenerateNuspecDependsOn);_GetNuspecDependencyPackageVersions - - - - - - - - - - diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.multitarget.nuspec b/src/Components/Components/src/Microsoft.AspNetCore.Components.multitarget.nuspec deleted file mode 100644 index 700ea95fa92c..000000000000 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.multitarget.nuspec +++ /dev/null @@ -1,26 +0,0 @@ - - - - $CommonMetadataElements$ - - - - - - - - - - - - - - - - $CommonFileElements$ - - - - - - diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.netcoreapp.nuspec b/src/Components/Components/src/Microsoft.AspNetCore.Components.netcoreapp.nuspec deleted file mode 100644 index 8561bc2f2f14..000000000000 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.netcoreapp.nuspec +++ /dev/null @@ -1,20 +0,0 @@ - - - - $CommonMetadataElements$ - - - - - - - - - - $CommonFileElements$ - - - - - - diff --git a/src/Components/Components/src/NavigationException.cs b/src/Components/Components/src/NavigationException.cs deleted file mode 100644 index 5acb891e6ff6..000000000000 --- a/src/Components/Components/src/NavigationException.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Exception thrown when an is not able to navigate to a different url. - /// - public class NavigationException : Exception - { - /// - /// Initializes a new instance. - /// - public NavigationException(string uri) - { - Location = uri; - } - - /// - /// Gets the uri to which navigation was attempted. - /// - public string Location { get; } - } -} diff --git a/src/Components/Components/src/NavigationManager.cs b/src/Components/Components/src/NavigationManager.cs deleted file mode 100644 index d75077026f06..000000000000 --- a/src/Components/Components/src/NavigationManager.cs +++ /dev/null @@ -1,269 +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 Microsoft.AspNetCore.Components.Routing; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Provides an abstraction for querying and mananging URI navigation. - /// - public abstract class NavigationManager - { - /// - /// An event that fires when the navigation location has changed. - /// - public event EventHandler LocationChanged - { - add - { - AssertInitialized(); - _locationChanged += value; - } - remove - { - AssertInitialized(); - _locationChanged -= value; - } - } - - private EventHandler _locationChanged; - - // For the baseUri it's worth storing as a System.Uri so we can do operations - // on that type. System.Uri gives us access to the original string anyway. - private Uri _baseUri; - - // The URI. Always represented an absolute URI. - private string _uri; - - private bool _isInitialized; - - /// - /// Gets or sets the current base URI. The is always represented as an absolute URI in string form with trailing slash. - /// Typically this corresponds to the 'href' attribute on the document's <base> element. - /// - /// - /// Setting will not trigger the event. - /// - public string BaseUri - { - get - { - AssertInitialized(); - return _baseUri.OriginalString; - } - protected set - { - if (value != null) - { - value = NormalizeBaseUri(value); - } - - _baseUri = new Uri(value, UriKind.Absolute); - } - } - - /// - /// Gets or sets the current URI. The is always represented as an absolute URI in string form. - /// - /// - /// Setting will not trigger the event. - /// - public string Uri - { - get - { - AssertInitialized(); - return _uri; - } - protected set - { - Validate(_baseUri, value); - _uri = value; - } - } - - /// - /// Navigates to the specified URI. - /// - /// The destination URI. This can be absolute, or relative to the base URI - /// (as returned by ). - /// If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router. - public void NavigateTo(string uri, bool forceLoad = false) - { - AssertInitialized(); - NavigateToCore(uri, forceLoad); - } - - /// - /// Navigates to the specified URI. - /// - /// The destination URI. This can be absolute, or relative to the base URI - /// (as returned by ). - /// If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router. - protected abstract void NavigateToCore(string uri, bool forceLoad); - - /// - /// Called to initialize BaseURI and current URI before these values are used for the first time. - /// Override and call this method to dynamically calculate these values. - /// - protected void Initialize(string baseUri, string uri) - { - // Make sure it's possible/safe to call this method from constructors of derived classes. - if (uri == null) - { - throw new ArgumentNullException(nameof(uri)); - } - - if (baseUri == null) - { - throw new ArgumentNullException(nameof(baseUri)); - } - - if (_isInitialized) - { - throw new InvalidOperationException($"'{GetType().Name}' already initialized."); - } - - _isInitialized = true; - - // Setting BaseUri before Uri so they get validated. - BaseUri = baseUri; - Uri = uri; - } - - /// - /// Allows derived classes to lazyly self-initialize. Implementations that support lazy-initialization should override - /// this method and call . - /// - protected virtual void EnsureInitialized() - { - } - - /// - /// Converts a relative URI into an absolute one (by resolving it - /// relative to the current absolute URI). - /// - /// The relative URI. - /// The absolute URI. - public Uri ToAbsoluteUri(string relativeUri) - { - AssertInitialized(); - return new Uri(_baseUri, relativeUri); - } - - /// - /// Given a base URI (e.g., one previously returned by ), - /// converts an absolute URI into one relative to the base URI prefix. - /// - /// An absolute URI that is within the space of the base URI. - /// A relative URI path. - public string ToBaseRelativePath(string uri) - { - if (uri.StartsWith(_baseUri.OriginalString, StringComparison.Ordinal)) - { - // The absolute URI must be of the form "{baseUri}something" (where - // baseUri ends with a slash), and from that we return "something" - return uri.Substring(_baseUri.OriginalString.Length); - } - - var hashIndex = uri.IndexOf('#'); - var uriWithoutHash = hashIndex < 0 ? uri : uri.Substring(0, hashIndex); - if ($"{uriWithoutHash}/".Equals(_baseUri.OriginalString, StringComparison.Ordinal)) - { - // Special case: for the base URI "/something/", if you're at - // "/something" then treat it as if you were at "/something/" (i.e., - // with the trailing slash). It's a bit ambiguous because we don't know - // whether the server would return the same page whether or not the - // slash is present, but ASP.NET Core at least does by default when - // using PathBase. - return uri.Substring(_baseUri.OriginalString.Length - 1); - } - - var message = $"The URI '{uri}' is not contained by the base URI '{_baseUri}'."; - throw new ArgumentException(message); - } - - internal static string NormalizeBaseUri(string baseUri) - { - var lastSlashIndex = baseUri.LastIndexOf('/'); - if (lastSlashIndex >= 0) - { - baseUri = baseUri.Substring(0, lastSlashIndex + 1); - } - - return baseUri; - } - - /// - /// Triggers the event with the current URI value. - /// - protected void NotifyLocationChanged(bool isInterceptedLink) - { - try - { - _locationChanged?.Invoke(this, new LocationChangedEventArgs(_uri, isInterceptedLink)); - } - catch (Exception ex) - { - throw new LocationChangeException("An exception occurred while dispatching a location changed event.", ex); - } - } - - private void AssertInitialized() - { - if (!_isInitialized) - { - EnsureInitialized(); - } - - if (!_isInitialized) - { - throw new InvalidOperationException($"'{GetType().Name}' has not been initialized."); - } - } - - private static bool TryGetLengthOfBaseUriPrefix(Uri baseUri, string uri, out int length) - { - if (uri.StartsWith(baseUri.OriginalString, StringComparison.Ordinal)) - { - // The absolute URI must be of the form "{baseUri}something" (where - // baseUri ends with a slash), and from that we return "something" - length = baseUri.OriginalString.Length; - return true; - } - - var hashIndex = uri.IndexOf('#'); - var uriWithoutHash = hashIndex < 0 ? uri : uri.Substring(0, hashIndex); - if ($"{uriWithoutHash}/".Equals(baseUri.OriginalString, StringComparison.Ordinal)) - { - // Special case: for the base URI "/something/", if you're at - // "/something" then treat it as if you were at "/something/" (i.e., - // with the trailing slash). It's a bit ambiguous because we don't know - // whether the server would return the same page whether or not the - // slash is present, but ASP.NET Core at least does by default when - // using PathBase. - length = baseUri.OriginalString.Length - 1; - return true; - } - - length = 0; - return false; - } - - private static void Validate(Uri baseUri, string uri) - { - if (baseUri == null || uri == null) - { - return; - } - - if (!TryGetLengthOfBaseUriPrefix(baseUri, uri, out _)) - { - var message = $"The URI '{uri}' is not contained by the base URI '{baseUri}'."; - throw new ArgumentException(message); - } - } - } -} diff --git a/src/Components/Components/src/OwningComponentBase.cs b/src/Components/Components/src/OwningComponentBase.cs deleted file mode 100644 index d5bcecb1f78a..000000000000 --- a/src/Components/Components/src/OwningComponentBase.cs +++ /dev/null @@ -1,100 +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 Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// A base class that creates a service provider scope. - /// - /// - /// Use the class as a base class to author components that control - /// the lifetime of a service provider scope. This is useful when using a transient or scoped service that - /// requires disposal such as a repository or database abstraction. Using - /// as a base class ensures that the service provider scope is disposed with the component. - /// - public abstract class OwningComponentBase : ComponentBase, IDisposable - { - private IServiceScope _scope; - - [Inject] IServiceScopeFactory ScopeFactory { get; set; } - - /// - /// Gets a value determining if the component and associated services have been disposed. - /// - protected bool IsDisposed { get; private set; } - - /// - /// Gets the scoped that is associated with this component. - /// - protected IServiceProvider ScopedServices - { - get - { - if (ScopeFactory == null) - { - throw new InvalidOperationException("Services cannot be accessed before the component is initialized."); - } - - if (IsDisposed) - { - throw new ObjectDisposedException(GetType().Name); - } - - _scope ??= ScopeFactory.CreateScope(); - return _scope.ServiceProvider; - } - } - - void IDisposable.Dispose() - { - if (!IsDisposed) - { - _scope?.Dispose(); - _scope = null; - Dispose(disposing: true); - IsDisposed = true; - } - } - - /// - protected virtual void Dispose(bool disposing) - { - } - } - - /// - /// A base class that creates a service provider scope, and resolves a service of type . - /// - /// The service type. - /// - /// Use the class as a base class to author components that control - /// the lifetime of a service or multiple services. This is useful when using a transient or scoped service that - /// requires disposal such as a repository or database abstraction. Using - /// as a base class ensures that the service and relates services that share its scope are disposed with the component. - /// - public abstract class OwningComponentBase : OwningComponentBase, IDisposable - { - private TService _item; - - /// - /// Gets the that is associated with this component. - /// - protected TService Service - { - get - { - if (IsDisposed) - { - throw new ObjectDisposedException(GetType().Name); - } - - // We cache this because we don't know the lifetime. We have to assume that it could be transient. - _item ??= ScopedServices.GetRequiredService(); - return _item; - } - } - } -} diff --git a/src/Components/Components/src/ParameterAttribute.cs b/src/Components/Components/src/ParameterAttribute.cs deleted file mode 100644 index 8001f1cdb330..000000000000 --- a/src/Components/Components/src/ParameterAttribute.cs +++ /dev/null @@ -1,36 +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 Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Denotes the target member as a component parameter. - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public sealed class ParameterAttribute : Attribute - { - /// - /// Gets or sets a value that determines whether the parameter will capture values that - /// don't match any other parameter. - /// - /// - /// - /// allows a component to accept arbitrary additional - /// attributes, and pass them to another component, or some element of the underlying markup. - /// - /// - /// can be used on at most one parameter per component. - /// - /// - /// should only be applied to parameters of a type that - /// can be used with - /// such as . - /// - /// - public bool CaptureUnmatchedValues { get; set; } - } -} diff --git a/src/Components/Components/src/ParameterValue.cs b/src/Components/Components/src/ParameterValue.cs deleted file mode 100644 index c080880de243..000000000000 --- a/src/Components/Components/src/ParameterValue.cs +++ /dev/null @@ -1,35 +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 -{ - /// - /// Represents a single parameter supplied to an - /// by its parent in the render tree. - /// - public readonly struct ParameterValue - { - internal ParameterValue(string name, object value, bool cascading) - { - Name = name; - Value = value; - Cascading = cascading; - } - - /// - /// Gets the name of the parameter. - /// - public string Name { get; } - - /// - /// Gets the value being supplied for the parameter. - /// - public object Value { get; } - - /// - /// Gets a value to indicate whether the parameter is cascading, meaning that it - /// was supplied by a . - /// - public bool Cascading { get; } - } -} diff --git a/src/Components/Components/src/ParameterView.cs b/src/Components/Components/src/ParameterView.cs deleted file mode 100644 index 33f87a50627c..000000000000 --- a/src/Components/Components/src/ParameterView.cs +++ /dev/null @@ -1,375 +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 Microsoft.AspNetCore.Components.Reflection; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Represents a collection of parameters supplied to an - /// by its parent in the render tree. - /// - public readonly struct ParameterView - { - private const string GeneratedParameterViewElementName = "__ARTIFICIAL_PARAMETER_VIEW"; - private static readonly RenderTreeFrame[] _emptyFrames = new RenderTreeFrame[] - { - RenderTreeFrame.Element(0, string.Empty).WithComponentSubtreeLength(1) - }; - - private static readonly ParameterView _empty = new ParameterView(ParameterViewLifetime.Unbound, _emptyFrames, 0, null); - - private readonly ParameterViewLifetime _lifetime; - private readonly RenderTreeFrame[] _frames; - private readonly int _ownerIndex; - private readonly IReadOnlyList _cascadingParametersOrNull; - - internal ParameterView(in ParameterViewLifetime lifetime, RenderTreeFrame[] frames, int ownerIndex) - : this(lifetime, frames, ownerIndex, null) - { - } - - private ParameterView(in ParameterViewLifetime lifetime, RenderTreeFrame[] frames, int ownerIndex, IReadOnlyList cascadingParametersOrNull) - { - _lifetime = lifetime; - _frames = frames; - _ownerIndex = ownerIndex; - _cascadingParametersOrNull = cascadingParametersOrNull; - } - - /// - /// Gets an empty . - /// - public static ParameterView Empty => _empty; - - internal ParameterViewLifetime Lifetime => _lifetime; - - /// - /// Returns an enumerator that iterates through the . - /// - /// The enumerator. - public Enumerator GetEnumerator() - { - _lifetime.AssertNotExpired(); - return new Enumerator(_frames, _ownerIndex, _cascadingParametersOrNull); - } - - /// - /// Gets the value of the parameter with the specified name. - /// - /// The type of the value. - /// The name of the parameter. - /// Receives the result, if any. - /// True if a matching parameter was found; false otherwise. - public bool TryGetValue(string parameterName, out TValue result) - { - foreach (var entry in this) - { - if (string.Equals(entry.Name, parameterName)) - { - result = (TValue)entry.Value; - return true; - } - } - - result = default; - return false; - } - - /// - /// Gets the value of the parameter with the specified name, or a default value - /// if no such parameter exists in the collection. - /// - /// The type of the value. - /// The name of the parameter. - /// The parameter value if found; otherwise the default value for the specified type. - public TValue GetValueOrDefault(string parameterName) - => GetValueOrDefault(parameterName, default); - - /// - /// Gets the value of the parameter with the specified name, or a specified default value - /// if no such parameter exists in the collection. - /// - /// The type of the value. - /// The name of the parameter. - /// The default value to return if no such parameter exists in the collection. - /// The parameter value if found; otherwise . - public TValue GetValueOrDefault(string parameterName, TValue defaultValue) - => TryGetValue(parameterName, out TValue result) ? result : defaultValue; - - /// - /// Returns a dictionary populated with the contents of the . - /// - /// A dictionary populated with the contents of the . - public IReadOnlyDictionary ToDictionary() - { - var result = new Dictionary(); - foreach (var entry in this) - { - result[entry.Name] = entry.Value; - } - return result; - } - - internal ParameterView WithCascadingParameters(IReadOnlyList cascadingParameters) - => new ParameterView(_lifetime, _frames, _ownerIndex, cascadingParameters); - - // It's internal because there isn't a known use case for user code comparing - // ParameterView instances, and even if there was, it's unlikely it should - // use these equality rules which are designed for their effect on rendering. - internal bool DefinitelyEquals(ParameterView oldParameters) - { - // In general we can't detect mutations on arbitrary objects. We can't trust - // things like .Equals or .GetHashCode because they usually only tell us about - // shallow changes, not deep mutations. So we return false if both: - // [1] All the parameters are known to be immutable (i.e., Type.IsPrimitive - // or is in a known set of common immutable types) - // [2] And all the parameter values are equal to their previous values - // Otherwise be conservative and return false. - // To make this check cheaper, since parameters are virtually always generated in - // a deterministic order, we don't bother to account for reordering, so if any - // of the names don't match sequentially we just return false too. - // - // The logic here may look kind of epic, and would certainly be simpler if we - // used ParameterEnumerator.GetEnumerator(), but it's perf-critical and this - // implementation requires a lot fewer instructions than a GetEnumerator-based one. - - var oldIndex = oldParameters._ownerIndex; - var newIndex = _ownerIndex; - var oldEndIndexExcl = oldIndex + oldParameters._frames[oldIndex].ComponentSubtreeLength; - var newEndIndexExcl = newIndex + _frames[newIndex].ComponentSubtreeLength; - while (true) - { - // First, stop if we've reached the end of either subtree - oldIndex++; - newIndex++; - var oldFinished = oldIndex == oldEndIndexExcl; - var newFinished = newIndex == newEndIndexExcl; - if (oldFinished || newFinished) - { - return oldFinished == newFinished; // Same only if we have same number of parameters - } - else - { - // Since neither subtree has finished, it's safe to read the next frame from both - ref var oldFrame = ref oldParameters._frames[oldIndex]; - ref var newFrame = ref _frames[newIndex]; - - // Stop if we've reached the end of either subtree's sequence of attributes - oldFinished = oldFrame.FrameType != RenderTreeFrameType.Attribute; - newFinished = newFrame.FrameType != RenderTreeFrameType.Attribute; - if (oldFinished || newFinished) - { - return oldFinished == newFinished; // Same only if we have same number of parameters - } - else - { - if (!string.Equals(oldFrame.AttributeName, newFrame.AttributeName, StringComparison.Ordinal)) - { - return false; // Different names - } - - var oldValue = oldFrame.AttributeValue; - var newValue = newFrame.AttributeValue; - if (ChangeDetection.MayHaveChanged(oldValue, newValue)) - { - return false; - } - } - } - } - } - - internal void CaptureSnapshot(ArrayBuilder builder) - { - builder.Clear(); - - var numEntries = 0; - foreach (var entry in this) - { - numEntries++; - } - - // We need to prefix the captured frames with an "owner" frame that - // describes the length of the buffer so that ParameterView - // knows how far to iterate through it. - var owner = RenderTreeFrame.PlaceholderChildComponentWithSubtreeLength(1 + numEntries); - builder.Append(owner); - - if (numEntries > 0) - { - builder.Append(_frames, _ownerIndex + 1, numEntries); - } - } - - /// - /// Creates a new from the given . - /// - /// The with the parameters. - /// A . - public static ParameterView FromDictionary(IDictionary parameters) - { - var frames = new RenderTreeFrame[parameters.Count + 1]; - frames[0] = RenderTreeFrame.Element(0, GeneratedParameterViewElementName) - .WithElementSubtreeLength(frames.Length); - - var i = 0; - foreach (var kvp in parameters) - { - frames[++i] = RenderTreeFrame.Attribute(i, kvp.Key, kvp.Value); - } - - return new ParameterView(ParameterViewLifetime.Unbound, frames, 0); - } - - /// - /// For each parameter property on , updates its value to - /// match the corresponding entry in the . - /// - /// An object that has a public writable property matching each parameter's name and type. - public void SetParameterProperties(object target) - { - if (target is null) - { - throw new ArgumentNullException(nameof(target)); - } - - ComponentProperties.SetProperties(this, target); - } - - /// - /// An enumerator that iterates through a . - /// - - // Note that this intentionally does not implement IEnumerator<>. This is the same pattern as Span<>.Enumerator - // it's valid to foreach over a type that doesn't implement IEnumerator<>. - public struct Enumerator - { - private RenderTreeFrameParameterEnumerator _directParamsEnumerator; - private CascadingParameterEnumerator _cascadingParameterEnumerator; - private bool _isEnumeratingDirectParams; - - internal Enumerator(RenderTreeFrame[] frames, int ownerIndex, IReadOnlyList cascadingParameters) - { - _directParamsEnumerator = new RenderTreeFrameParameterEnumerator(frames, ownerIndex); - _cascadingParameterEnumerator = new CascadingParameterEnumerator(cascadingParameters); - _isEnumeratingDirectParams = true; - } - - /// - /// Gets the current value of the enumerator. - /// - public ParameterValue Current => _isEnumeratingDirectParams - ? _directParamsEnumerator.Current - : _cascadingParameterEnumerator.Current; - - /// - /// Instructs the enumerator to move to the next value in the sequence. - /// - /// A flag to indicate whether or not there is a next value. - public bool MoveNext() - { - if (_isEnumeratingDirectParams) - { - if (_directParamsEnumerator.MoveNext()) - { - return true; - } - else - { - _isEnumeratingDirectParams = false; - } - } - - return _cascadingParameterEnumerator.MoveNext(); - } - } - - private struct RenderTreeFrameParameterEnumerator - { - private readonly RenderTreeFrame[] _frames; - private readonly int _ownerIndex; - private readonly int _ownerDescendantsEndIndexExcl; - private int _currentIndex; - private ParameterValue _current; - - internal RenderTreeFrameParameterEnumerator(RenderTreeFrame[] frames, int ownerIndex) - { - _frames = frames; - _ownerIndex = ownerIndex; - _ownerDescendantsEndIndexExcl = ownerIndex + _frames[ownerIndex].ElementSubtreeLength; - _currentIndex = ownerIndex; - _current = default; - } - - public ParameterValue Current => _current; - - public bool MoveNext() - { - // Stop iteration if you get to the end of the owner's descendants... - var nextIndex = _currentIndex + 1; - if (nextIndex == _ownerDescendantsEndIndexExcl) - { - return false; - } - - // ... or if you get to its first non-attribute descendant (because attributes - // are always before any other type of descendant) - if (_frames[nextIndex].FrameType != RenderTreeFrameType.Attribute) - { - return false; - } - - _currentIndex = nextIndex; - - ref var frame = ref _frames[_currentIndex]; - _current = new ParameterValue(frame.AttributeName, frame.AttributeValue, false); - - return true; - } - } - - private struct CascadingParameterEnumerator - { - private readonly IReadOnlyList _cascadingParameters; - private int _currentIndex; - private ParameterValue _current; - - public CascadingParameterEnumerator(IReadOnlyList cascadingParameters) - { - _cascadingParameters = cascadingParameters; - _currentIndex = -1; - _current = default; - } - - public ParameterValue Current => _current; - - public bool MoveNext() - { - // Bail out early if there are no cascading parameters - if (_cascadingParameters == null) - { - return false; - } - - var nextIndex = _currentIndex + 1; - if (nextIndex < _cascadingParameters.Count) - { - _currentIndex = nextIndex; - - var state = _cascadingParameters[_currentIndex]; - _current = new ParameterValue(state.LocalValueName, state.ValueSupplier.CurrentValue, true); - return true; - } - else - { - return false; - } - } - } - } -} diff --git a/src/Components/Components/src/PlatformInfo.cs b/src/Components/Components/src/PlatformInfo.cs deleted file mode 100644 index 81338cab5813..000000000000 --- a/src/Components/Components/src/PlatformInfo.cs +++ /dev/null @@ -1,17 +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.InteropServices; - -namespace Microsoft.AspNetCore.Components -{ - internal static class PlatformInfo - { - public static bool IsWebAssembly { get; } - - static PlatformInfo() - { - IsWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY")); - } - } -} diff --git a/src/Components/Components/src/Properties/AssemblyInfo.cs b/src/Components/Components/src/Properties/AssemblyInfo.cs deleted file mode 100644 index d5aa38e01d07..000000000000 --- a/src/Components/Components/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Build.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Authorization.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Forms.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Server.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Web.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Components/Components/src/Reflection/ComponentProperties.cs b/src/Components/Components/src/Reflection/ComponentProperties.cs deleted file mode 100644 index 0b85a66a84c7..000000000000 --- a/src/Components/Components/src/Reflection/ComponentProperties.cs +++ /dev/null @@ -1,288 +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.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; - -namespace Microsoft.AspNetCore.Components.Reflection -{ - internal static class ComponentProperties - { - private const BindingFlags _bindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase; - - // Right now it's not possible for a component to define a Parameter and a Cascading Parameter with - // the same name. We don't give you a way to express this in code (would create duplicate properties), - // and we don't have the ability to represent it in our data structures. - private readonly static ConcurrentDictionary _cachedWritersByType - = new ConcurrentDictionary(); - - public static void SetProperties(in ParameterView parameters, object target) - { - if (target == null) - { - throw new ArgumentNullException(nameof(target)); - } - - var targetType = target.GetType(); - if (!_cachedWritersByType.TryGetValue(targetType, out var writers)) - { - writers = new WritersForType(targetType); - _cachedWritersByType[targetType] = writers; - } - - // The logic is split up for simplicity now that we have CaptureUnmatchedValues parameters. - if (writers.CaptureUnmatchedValuesWriter == null) - { - // Logic for components without a CaptureUnmatchedValues parameter - foreach (var parameter in parameters) - { - var parameterName = parameter.Name; - if (!writers.WritersByName.TryGetValue(parameterName, out var writer)) - { - // Case 1: There is nowhere to put this value. - ThrowForUnknownIncomingParameterName(targetType, parameterName); - throw null; // Unreachable - } - else if (writer.Cascading && !parameter.Cascading) - { - // We don't allow you to set a cascading parameter with a non-cascading value. Put another way: - // cascading parameters are not part of the public API of a component, so it's not reasonable - // for someone to set it directly. - // - // If we find a strong reason for this to work in the future we can reverse our decision since - // this throws today. - ThrowForSettingCascadingParameterWithNonCascadingValue(targetType, parameterName); - throw null; // Unreachable - } - else if (!writer.Cascading && parameter.Cascading) - { - // We're giving a more specific error here because trying to set a non-cascading parameter - // with a cascading value is likely deliberate (but not supported), or is a bug in our code. - ThrowForSettingParameterWithCascadingValue(targetType, parameterName); - throw null; // Unreachable - } - - SetProperty(target, writer, parameterName, parameter.Value); - } - } - else - { - // Logic with components with a CaptureUnmatchedValues parameter - var isCaptureUnmatchedValuesParameterSetExplicitly = false; - Dictionary unmatched = null; - foreach (var parameter in parameters) - { - var parameterName = parameter.Name; - if (string.Equals(parameterName, writers.CaptureUnmatchedValuesPropertyName, StringComparison.OrdinalIgnoreCase)) - { - isCaptureUnmatchedValuesParameterSetExplicitly = true; - } - - var isUnmatchedValue = !writers.WritersByName.TryGetValue(parameterName, out var writer); - - if ((isUnmatchedValue && parameter.Cascading) || (writer != null && !writer.Cascading && parameter.Cascading)) - { - // Don't allow an "extra" cascading value to be collected - or don't allow a non-cascading - // parameter to be set with a cascading value. - // - // This is likely a bug in our infrastructure or an attempt to deliberately do something unsupported. - ThrowForSettingParameterWithCascadingValue(targetType, parameterName); - throw null; // Unreachable - - } - else if (isUnmatchedValue || - - // Allow unmatched parameters to collide with the names of cascading parameters. This is - // valid because cascading parameter names are not part of the public API. There's no - // way for the user of a component to know what the names of cascading parameters - // are. - (writer.Cascading && !parameter.Cascading)) - { - unmatched ??= new Dictionary(StringComparer.OrdinalIgnoreCase); - unmatched[parameterName] = parameter.Value; - } - else - { - Debug.Assert(writer != null); - SetProperty(target, writer, parameterName, parameter.Value); - } - } - - if (unmatched != null && isCaptureUnmatchedValuesParameterSetExplicitly) - { - // This has to be an error because we want to allow users to set the CaptureUnmatchedValues - // parameter explicitly and .... - // 1. We don't ever want to mutate a value the user gives us. - // 2. We also don't want to implicitly copy a value the user gives us. - // - // Either one of those implementation choices would do something unexpected. - ThrowForCaptureUnmatchedValuesConflict(targetType, writers.CaptureUnmatchedValuesPropertyName, unmatched); - throw null; // Unreachable - } - else if (unmatched != null) - { - // We had some unmatched values, set the CaptureUnmatchedValues property - SetProperty(target, writers.CaptureUnmatchedValuesWriter, writers.CaptureUnmatchedValuesPropertyName, unmatched); - } - } - - static void SetProperty(object target, IPropertySetter writer, string parameterName, object value) - { - try - { - writer.SetValue(target, value); - } - catch (Exception ex) - { - throw new InvalidOperationException( - $"Unable to set property '{parameterName}' on object of " + - $"type '{target.GetType().FullName}'. The error was: {ex.Message}", ex); - } - } - } - - internal static IEnumerable GetCandidateBindableProperties(Type targetType) - => MemberAssignment.GetPropertiesIncludingInherited(targetType, _bindablePropertyFlags); - - private static void ThrowForUnknownIncomingParameterName(Type targetType, string parameterName) - { - // We know we're going to throw by this stage, so it doesn't matter that the following - // reflection code will be slow. We're just trying to help developers see what they did wrong. - var propertyInfo = targetType.GetProperty(parameterName, _bindablePropertyFlags); - if (propertyInfo != null) - { - if (!propertyInfo.IsDefined(typeof(ParameterAttribute)) && !propertyInfo.IsDefined(typeof(CascadingParameterAttribute))) - { - throw new InvalidOperationException( - $"Object of type '{targetType.FullName}' has a property matching the name '{parameterName}', " + - $"but it does not have [{nameof(ParameterAttribute)}] or [{nameof(CascadingParameterAttribute)}] applied."); - } - else - { - // This should not happen - throw new InvalidOperationException( - $"No writer was cached for the property '{propertyInfo.Name}' on type '{targetType.FullName}'."); - } - } - else - { - throw new InvalidOperationException( - $"Object of type '{targetType.FullName}' does not have a property " + - $"matching the name '{parameterName}'."); - } - } - - private static void ThrowForSettingCascadingParameterWithNonCascadingValue(Type targetType, string parameterName) - { - throw new InvalidOperationException( - $"Object of type '{targetType.FullName}' has a property matching the name '{parameterName}', " + - $"but it does not have [{nameof(ParameterAttribute)}] applied."); - } - - private static void ThrowForSettingParameterWithCascadingValue(Type targetType, string parameterName) - { - throw new InvalidOperationException( - $"The property '{parameterName}' on component type '{targetType.FullName}' cannot be set " + - $"using a cascading value."); - } - - private static void ThrowForCaptureUnmatchedValuesConflict(Type targetType, string parameterName, Dictionary unmatched) - { - throw new InvalidOperationException( - $"The property '{parameterName}' on component type '{targetType.FullName}' cannot be set explicitly " + - $"when also used to capture unmatched values. Unmatched values:" + Environment.NewLine + - string.Join(Environment.NewLine, unmatched.Keys.OrderBy(k => k))); - } - - private static void ThrowForMultipleCaptureUnmatchedValuesParameters(Type targetType) - { - // We don't care about perf here, we want to report an accurate and useful error. - var propertyNames = targetType - .GetProperties(_bindablePropertyFlags) - .Where(p => p.GetCustomAttribute()?.CaptureUnmatchedValues == true) - .Select(p => p.Name) - .OrderBy(p => p) - .ToArray(); - - throw new InvalidOperationException( - $"Multiple properties were found on component type '{targetType.FullName}' with " + - $"'{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Only a single property " + - $"per type can use '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Properties:" + Environment.NewLine + - string.Join(Environment.NewLine, propertyNames)); - } - - private static void ThrowForInvalidCaptureUnmatchedValuesParameterType(Type targetType, PropertyInfo propertyInfo) - { - throw new InvalidOperationException( - $"The property '{propertyInfo.Name}' on component type '{targetType.FullName}' cannot be used " + - $"with '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}' because it has the wrong type. " + - $"The property must be assignable from 'Dictionary'."); - } - - private class WritersForType - { - public WritersForType(Type targetType) - { - WritersByName = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var propertyInfo in GetCandidateBindableProperties(targetType)) - { - var parameterAttribute = propertyInfo.GetCustomAttribute(); - var cascadingParameterAttribute = propertyInfo.GetCustomAttribute(); - var isParameter = parameterAttribute != null || cascadingParameterAttribute != null; - if (!isParameter) - { - continue; - } - - var propertyName = propertyInfo.Name; - if (parameterAttribute != null && (propertyInfo.SetMethod == null || !propertyInfo.SetMethod.IsPublic)) - { - throw new InvalidOperationException( - $"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public."); - } - - var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null); - - if (WritersByName.ContainsKey(propertyName)) - { - throw new InvalidOperationException( - $"The type '{targetType.FullName}' declares more than one parameter matching the " + - $"name '{propertyName.ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique."); - } - - WritersByName.Add(propertyName, propertySetter); - - if (parameterAttribute != null && parameterAttribute.CaptureUnmatchedValues) - { - // This is an "Extra" parameter. - // - // There should only be one of these. - if (CaptureUnmatchedValuesWriter != null) - { - ThrowForMultipleCaptureUnmatchedValuesParameters(targetType); - } - - // It must be able to hold a Dictionary since that's what we create. - if (!propertyInfo.PropertyType.IsAssignableFrom(typeof(Dictionary))) - { - ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo); - } - - CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: false); - CaptureUnmatchedValuesPropertyName = propertyInfo.Name; - } - } - } - - public Dictionary WritersByName { get; } - - public IPropertySetter CaptureUnmatchedValuesWriter { get; } - - public string CaptureUnmatchedValuesPropertyName { get; } - } - } -} diff --git a/src/Components/Components/src/Reflection/IPropertySetter.cs b/src/Components/Components/src/Reflection/IPropertySetter.cs deleted file mode 100644 index d6a60e2395ae..000000000000 --- a/src/Components/Components/src/Reflection/IPropertySetter.cs +++ /dev/null @@ -1,12 +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.Reflection -{ - internal interface IPropertySetter - { - bool Cascading { get; } - - void SetValue(object target, object value); - } -} diff --git a/src/Components/Components/src/Reflection/MemberAssignment.cs b/src/Components/Components/src/Reflection/MemberAssignment.cs deleted file mode 100644 index ab0cf6b1e781..000000000000 --- a/src/Components/Components/src/Reflection/MemberAssignment.cs +++ /dev/null @@ -1,87 +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.Linq; -using System.Reflection; - -namespace Microsoft.AspNetCore.Components.Reflection -{ - internal class MemberAssignment - { - public static IEnumerable GetPropertiesIncludingInherited( - Type type, BindingFlags bindingFlags) - { - var dictionary = new Dictionary>(); - - while (type != null) - { - var properties = type.GetProperties(bindingFlags) - .Where(prop => prop.DeclaringType == type); - foreach (var property in properties) - { - if (!dictionary.TryGetValue(property.Name, out var others)) - { - others = new List(); - dictionary.Add(property.Name, others); - } - - if (others.Any(other => other.GetMethod?.GetBaseDefinition() == property.GetMethod?.GetBaseDefinition())) - { - // This is an inheritance case. We can safely ignore the value of property since - // we have seen a more derived value. - continue; - } - - others.Add(property); - } - - type = type.BaseType; - } - - return dictionary.Values.SelectMany(p => p); - } - - public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property, bool cascading) - { - if (property.SetMethod == null) - { - throw new InvalidOperationException($"Cannot provide a value for property " + - $"'{property.Name}' on type '{targetType.FullName}' because the property " + - $"has no setter."); - } - - return (IPropertySetter)Activator.CreateInstance( - typeof(PropertySetter<,>).MakeGenericType(targetType, property.PropertyType), - property.SetMethod, - cascading); - } - - class PropertySetter : IPropertySetter - { - private readonly Action _setterDelegate; - - public PropertySetter(MethodInfo setMethod, bool cascading) - { - _setterDelegate = (Action)Delegate.CreateDelegate( - typeof(Action), setMethod); - Cascading = cascading; - } - - public bool Cascading { get; } - - public void SetValue(object target, object value) - { - if (value == null) - { - _setterDelegate((TTarget)target, default); - } - else - { - _setterDelegate((TTarget)target, (TValue)value); - } - } - } - } -} diff --git a/src/Components/Components/src/RenderFragment.cs b/src/Components/Components/src/RenderFragment.cs deleted file mode 100644 index cf27ad2cc43e..000000000000 --- a/src/Components/Components/src/RenderFragment.cs +++ /dev/null @@ -1,22 +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.Rendering; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Represents a segment of UI content, implemented as a delegate that - /// writes the content to a . - /// - /// The to which the content should be written. - public delegate void RenderFragment(RenderTreeBuilder builder); - - /// - /// Represents a segment of UI content for an object of type , implemented as - /// a function that returns a . - /// - /// The type of object. - /// The value used to build the content. - public delegate RenderFragment RenderFragment(TValue value); -} diff --git a/src/Components/Components/src/RenderHandle.cs b/src/Components/Components/src/RenderHandle.cs deleted file mode 100644 index fb646feeee59..000000000000 --- a/src/Components/Components/src/RenderHandle.cs +++ /dev/null @@ -1,65 +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 Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Allows a component to interact with its renderer. - /// - public readonly struct RenderHandle - { - private readonly Renderer _renderer; - private readonly int _componentId; - - internal RenderHandle(Renderer renderer, int componentId) - { - _renderer = renderer ?? throw new System.ArgumentNullException(nameof(renderer)); - _componentId = componentId; - } - - /// - /// Gets the associated with the component. - /// - public Dispatcher Dispatcher - { - get - { - if (_renderer == null) - { - ThrowNotInitialized(); - } - - return _renderer.Dispatcher; - } - } - - /// - /// Gets a value that indicates whether the has been - /// initialized and is ready to use. - /// - public bool IsInitialized - => _renderer != null; - - /// - /// Notifies the renderer that the component should be rendered. - /// - /// The content that should be rendered. - public void Render(RenderFragment renderFragment) - { - if (_renderer == null) - { - ThrowNotInitialized(); - } - - _renderer.AddToRenderQueue(_componentId, renderFragment); - } - - private static void ThrowNotInitialized() - { - throw new InvalidOperationException("The render handle is not yet assigned."); - } - } -} diff --git a/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs b/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs deleted file mode 100644 index 2252000716dc..000000000000 --- a/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs +++ /dev/null @@ -1,31 +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; - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - internal static class ArrayBuilderExtensions - { - /// - /// Produces an structure describing the current contents. - /// - /// The . - public static ArrayRange ToRange(this ArrayBuilder builder) - => new ArrayRange(builder.Buffer, builder.Count); - - /// - /// Produces an structure describing the selected contents. - /// - /// The - /// The index of the first item in the segment. - /// One plus the index of the last item in the segment. - /// The . - public static ArrayBuilderSegment ToSegment(this ArrayBuilder builder, int fromIndexInclusive, int toIndexExclusive) - => new ArrayBuilderSegment(builder, fromIndexInclusive, toIndexExclusive - fromIndexInclusive); - } -} diff --git a/src/Components/Components/src/RenderTree/ArrayBuilderSegment.cs b/src/Components/Components/src/RenderTree/ArrayBuilderSegment.cs deleted file mode 100644 index 4820e2f5fda5..000000000000 --- a/src/Components/Components/src/RenderTree/ArrayBuilderSegment.cs +++ /dev/null @@ -1,67 +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; -using System.Collections.Generic; - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - /// The type of the elements in the array - // - // Represents a range of elements within an instance of . - public readonly struct ArrayBuilderSegment : IEnumerable - { - // The following fields are memory mapped to the WASM client. Do not re-order or use auto-properties. - private readonly ArrayBuilder _builder; - private readonly int _offset; - private readonly int _count; - - internal ArrayBuilderSegment(ArrayBuilder builder, int offset, int count) - { - _builder = builder; - _offset = offset; - _count = count; - } - - /// - /// Gets the current underlying array holding the segment's elements. - /// - public T[] Array => _builder?.Buffer; - - /// - /// Gets the offset into the underlying array holding the segment's elements. - /// - public int Offset => _offset; - - /// - /// Gets the number of items in the segment. - /// - public int Count => _count; - - /// - /// Gets the specified item from the segment. - /// - /// The index into the segment. - /// The array entry at the specified index within the segment. - public T this[int index] - => _builder.Buffer[_offset + index]; - - IEnumerator IEnumerable.GetEnumerator() - => ((IEnumerable)new ArraySegment(_builder.Buffer, _offset, _count)).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() - => ((IEnumerable)new ArraySegment(_builder.Buffer, _offset, _count)).GetEnumerator(); - - // TODO: If this assembly later moves to netstandard2.1, consider adding a public - // GetEnumerator method that returns ArraySegment.Enumerator to avoid boxing. - } -} diff --git a/src/Components/Components/src/RenderTree/ArrayRange.cs b/src/Components/Components/src/RenderTree/ArrayRange.cs deleted file mode 100644 index a980a9224645..000000000000 --- a/src/Components/Components/src/RenderTree/ArrayRange.cs +++ /dev/null @@ -1,51 +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. - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - /// - // - // Represents a range of elements in an array that are in use. - public readonly struct ArrayRange - { - /// - /// Gets the underlying array instance. - /// - public readonly T[] Array; - - /// - /// Gets the number of items in the array that are considered to be in use. - /// - public readonly int Count; - - /// - /// Constructs an instance of . - /// - /// The array. - /// The number of items in the array that are in use. - public ArrayRange(T[] array, int count) - { - Array = array; - Count = count; - } - - /// - /// Creates a shallow clone of the instance. - /// - /// - public ArrayRange Clone() - { - var buffer = new T[Count]; - System.Array.Copy(Array, buffer, Count); - return new ArrayRange(buffer, Count); - } - } -} diff --git a/src/Components/Components/src/RenderTree/EventFieldInfo.cs b/src/Components/Components/src/RenderTree/EventFieldInfo.cs deleted file mode 100644 index 129057ff73fb..000000000000 --- a/src/Components/Components/src/RenderTree/EventFieldInfo.cs +++ /dev/null @@ -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. - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in a future release. - /// - // - // Information supplied with an event notification that can be used to update an existing - // render tree to match the latest UI state when a form field has mutated. To determine - // which field has been mutated, the renderer matches it based on the event handler ID. - public class EventFieldInfo - { - /// - /// Identifies the component whose render tree contains the affected form field. - /// - public int ComponentId { get; set; } - - /// - /// Specifies the form field's new value. - /// - public object FieldValue { get; set; } - } -} diff --git a/src/Components/Components/src/RenderTree/RenderBatch.cs b/src/Components/Components/src/RenderTree/RenderBatch.cs deleted file mode 100644 index 55f3c02629dd..000000000000 --- a/src/Components/Components/src/RenderTree/RenderBatch.cs +++ /dev/null @@ -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. - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in a future release. - /// - // - // Describes a set of UI changes. - public readonly struct RenderBatch - { - /// - /// Gets the changes to components that were added or updated. - /// - public ArrayRange UpdatedComponents { get; } - - /// - /// Gets render frames that may be referenced by entries in . - /// For example, edit entries of type - /// will point to an entry in this array to specify the subtree to be prepended. - /// - public ArrayRange ReferenceFrames { get; } - - /// - /// Gets the IDs of the components that were disposed. - /// - public ArrayRange DisposedComponentIDs { get; } - - /// - /// Gets the IDs of the event handlers that were disposed. - /// - public ArrayRange DisposedEventHandlerIDs { get; } - - internal RenderBatch( - ArrayRange updatedComponents, - ArrayRange referenceFrames, - ArrayRange disposedComponentIDs, - ArrayRange disposedEventHandlerIDs) - { - UpdatedComponents = updatedComponents; - ReferenceFrames = referenceFrames; - DisposedComponentIDs = disposedComponentIDs; - DisposedEventHandlerIDs = disposedEventHandlerIDs; - } - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeDiff.cs b/src/Components/Components/src/RenderTree/RenderTreeDiff.cs deleted file mode 100644 index 4947029ab2e2..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeDiff.cs +++ /dev/null @@ -1,36 +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. - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - // - // Describes changes to a component's render tree between successive renders. - public readonly struct RenderTreeDiff - { - /// - /// Gets the ID of the component. - /// - public readonly int ComponentId; - - /// - /// Gets the changes to the render tree since a previous state. - /// - public readonly ArrayBuilderSegment Edits; - - internal RenderTreeDiff( - int componentId, - ArrayBuilderSegment entries) - { - ComponentId = componentId; - Edits = entries; - } - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs deleted file mode 100644 index 11f5540f4c6c..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs +++ /dev/null @@ -1,998 +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 Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - internal static class RenderTreeDiffBuilder - { - enum DiffAction { Match, Insert, Delete } - - // We use int.MinValue to signal this special case because (1) it would never be used by - // the Razor compiler or by accident in developer code, and (2) we know it will always - // hit the "old < new" code path during diffing so we only have to check for it in one place. - public const int SystemAddedAttributeSequenceNumber = int.MinValue; - - public static RenderTreeDiff ComputeDiff( - Renderer renderer, - RenderBatchBuilder batchBuilder, - int componentId, - ArrayRange oldTree, - ArrayRange newTree) - { - var editsBuffer = batchBuilder.EditsBuffer; - var editsBufferStartLength = editsBuffer.Count; - - var diffContext = new DiffContext(renderer, batchBuilder, componentId, oldTree.Array, newTree.Array); - AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count); - - var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count); - return new RenderTreeDiff(componentId, editsSegment); - } - - public static void DisposeFrames(RenderBatchBuilder batchBuilder, ArrayRange frames) - => DisposeFramesInRange(batchBuilder, frames.Array, 0, frames.Count); - - private static void AppendDiffEntriesForRange( - ref DiffContext diffContext, - int oldStartIndex, int oldEndIndexExcl, - int newStartIndex, int newEndIndexExcl) - { - // This is deliberately a very large method. Parts of it could be factored out - // into other private methods, but doing so comes at a consequential perf cost, - // because it involves so much parameter passing. You can think of the code here - // as being several private methods (delimited by #region) pre-inlined. - // - // A naive "extract methods"-type refactoring will worsen perf by about 10%. So, - // if you plan to refactor this, be sure to benchmark the old and new versions - // on Mono WebAssembly. - - var origOldStartIndex = oldStartIndex; - var origNewStartIndex = newStartIndex; - var hasMoreOld = oldEndIndexExcl > oldStartIndex; - var hasMoreNew = newEndIndexExcl > newStartIndex; - var prevOldSeq = -1; - var prevNewSeq = -1; - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - var matchWithNewTreeIndex = -1; // Only used when action == DiffAction.Match - Dictionary keyedItemInfos = null; - - try - { - while (hasMoreOld || hasMoreNew) - { - DiffAction action; - - #region "Read keys and sequence numbers" - int oldSeq, newSeq; - object oldKey, newKey; - if (hasMoreOld) - { - ref var oldFrame = ref oldTree[oldStartIndex]; - oldSeq = oldFrame.Sequence; - oldKey = KeyValue(ref oldFrame); - } - else - { - oldSeq = int.MaxValue; - oldKey = null; - } - - if (hasMoreNew) - { - ref var newFrame = ref newTree[newStartIndex]; - newSeq = newFrame.Sequence; - newKey = KeyValue(ref newFrame); - } - else - { - newSeq = int.MaxValue; - newKey = null; - } - #endregion - - // If there's a key on either side, prefer matching by key not sequence - if (oldKey != null || newKey != null) - { - #region "Get diff action by matching on key" - // Regardless of whether these two keys match, since you are using keys, we want to validate at this point that there are no clashes - // so ensure we've built the dictionary that will be used for lookups if any don't match - keyedItemInfos ??= BuildKeyToInfoLookup(diffContext, origOldStartIndex, oldEndIndexExcl, origNewStartIndex, newEndIndexExcl); - - if (Equals(oldKey, newKey)) - { - // Keys match - action = DiffAction.Match; - matchWithNewTreeIndex = newStartIndex; - } - else - { - // Keys don't match - var oldKeyItemInfo = oldKey != null ? keyedItemInfos[oldKey] : new KeyedItemInfo(-1, -1); - var newKeyItemInfo = newKey != null ? keyedItemInfos[newKey] : new KeyedItemInfo(-1, -1); - var oldKeyIsInNewTree = oldKeyItemInfo.NewIndex >= 0; - var newKeyIsInOldTree = newKeyItemInfo.OldIndex >= 0; - - // If either key is not in the other tree, we can handle it as an insert or a delete - // on this iteration. We're only forced to use the move logic that's not the case - // (i.e., both keys are in both trees) - if (oldKeyIsInNewTree && newKeyIsInOldTree) - { - // It's a move - // Since the recipient of the diff script already has the old frame (the one with oldKey) - // at the current siblingIndex, recurse into oldKey and update its descendants in place. - // We re-order the frames afterwards. - action = DiffAction.Match; - matchWithNewTreeIndex = oldKeyItemInfo.NewIndex; - - // Track the post-edit sibling indices of the moved items - // Since diffContext.SiblingIndex only increases, we can be sure the values we - // write at this point will remain correct, because there won't be any further - // insertions/deletions at smaller sibling indices. - keyedItemInfos[oldKey] = oldKeyItemInfo.WithOldSiblingIndex(diffContext.SiblingIndex); - keyedItemInfos[newKey] = newKeyItemInfo.WithNewSiblingIndex(diffContext.SiblingIndex); - } - else if (!hasMoreNew) - { - // If we've run out of new items, we must be looking at just an old item, so delete it - action = DiffAction.Delete; - } - else - { - // It's an insertion or a deletion, or both - // If the new key is in both trees, but the old key isn't, then the old item was deleted - // Otherwise, it's either an insertion or *both* insertion+deletion, so pick insertion and get the deletion on the next iteration if needed - action = newKeyIsInOldTree ? DiffAction.Delete : DiffAction.Insert; - } - } - #endregion - } - else - { - #region "Get diff action by matching on sequence number" - // Neither side is keyed, so match by sequence number - if (oldSeq == newSeq) - { - // Sequences match - action = DiffAction.Match; - matchWithNewTreeIndex = newStartIndex; - } - else - { - // Sequences don't match - var oldLoopedBack = oldSeq <= prevOldSeq; - var newLoopedBack = newSeq <= prevNewSeq; - if (oldLoopedBack == newLoopedBack) - { - // Both sequences are proceeding through the same loop block, so do a simple - // preordered merge join (picking from whichever side brings us closer to being - // back in sync) - action = newSeq < oldSeq ? DiffAction.Insert : DiffAction.Delete; - - if (oldLoopedBack) - { - // If both old and new have now looped back, we must reset their 'looped back' - // tracker so we can treat them as proceeding through the same loop block - prevOldSeq = -1; - prevNewSeq = -1; - } - } - else if (oldLoopedBack) - { - // Old sequence looped back but new one didn't - // The new sequence either has some extra trailing elements in the current loop block - // which we should insert, or omits some old trailing loop blocks which we should delete - // TODO: Find a way of not recomputing this next flag on every iteration - var newLoopsBackLater = false; - for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++) - { - if (newTree[testIndex].Sequence < newSeq) - { - newLoopsBackLater = true; - break; - } - } - - // If the new sequence loops back later to an earlier point than this, - // then we know it's part of the existing loop block (so should be inserted). - // If not, then it's unrelated to the previous loop block (so we should treat - // the old items as trailing loop blocks to be removed). - action = newLoopsBackLater ? DiffAction.Insert : DiffAction.Delete; - } - else - { - // New sequence looped back but old one didn't - // The old sequence either has some extra trailing elements in the current loop block - // which we should delete, or the new sequence has extra trailing loop blocks which we - // should insert - // TODO: Find a way of not recomputing this next flag on every iteration - var oldLoopsBackLater = false; - for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++) - { - if (oldTree[testIndex].Sequence < oldSeq) - { - oldLoopsBackLater = true; - break; - } - } - - // If the old sequence loops back later to an earlier point than this, - // then we know it's part of the existing loop block (so should be removed). - // If not, then it's unrelated to the previous loop block (so we should treat - // the new items as trailing loop blocks to be inserted). - action = oldLoopsBackLater ? DiffAction.Delete : DiffAction.Insert; - } - } - #endregion - } - - #region "Apply diff action" - switch (action) - { - case DiffAction.Match: - AppendDiffEntriesForFramesWithSameSequence(ref diffContext, oldStartIndex, matchWithNewTreeIndex); - oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); - newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); - hasMoreOld = oldEndIndexExcl > oldStartIndex; - hasMoreNew = newEndIndexExcl > newStartIndex; - prevOldSeq = oldSeq; - prevNewSeq = newSeq; - break; - case DiffAction.Insert: - InsertNewFrame(ref diffContext, newStartIndex); - newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); - hasMoreNew = newEndIndexExcl > newStartIndex; - prevNewSeq = newSeq; - break; - case DiffAction.Delete: - RemoveOldFrame(ref diffContext, oldStartIndex); - oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); - hasMoreOld = oldEndIndexExcl > oldStartIndex; - prevOldSeq = oldSeq; - break; - } - #endregion - } - - #region "Write permutations list" - if (keyedItemInfos != null) - { - var hasPermutations = false; - foreach (var keyValuePair in keyedItemInfos) - { - var value = keyValuePair.Value; - if (value.OldSiblingIndex >= 0 && value.NewSiblingIndex >= 0) - { - // This item moved - hasPermutations = true; - diffContext.Edits.Append( - RenderTreeEdit.PermutationListEntry(value.OldSiblingIndex, value.NewSiblingIndex)); - } - } - - if (hasPermutations) - { - // It's much easier for the recipient to handle if we're explicit about - // when the list is finished - diffContext.Edits.Append(RenderTreeEdit.PermutationListEnd()); - } - } - #endregion - } - finally - { - if (keyedItemInfos != null) - { - keyedItemInfos.Clear(); - diffContext.KeyedItemInfoDictionaryPool.Return(keyedItemInfos); - } - } - } - - private static Dictionary BuildKeyToInfoLookup(DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) - { - var result = diffContext.KeyedItemInfoDictionaryPool.Get(); - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - - while (oldStartIndex < oldEndIndexExcl) - { - ref var frame = ref oldTree[oldStartIndex]; - var key = KeyValue(ref frame); - if (key != null) - { - if (result.ContainsKey(key)) - { - ThrowExceptionForDuplicateKey(key); - } - - result[key] = new KeyedItemInfo(oldStartIndex, -1); - } - - oldStartIndex = NextSiblingIndex(frame, oldStartIndex); - } - - while (newStartIndex < newEndIndexExcl) - { - ref var frame = ref newTree[newStartIndex]; - var key = KeyValue(ref frame); - if (key != null) - { - if (!result.TryGetValue(key, out var existingEntry)) - { - result[key] = new KeyedItemInfo(-1, newStartIndex); - } - else - { - if (existingEntry.NewIndex >= 0) - { - ThrowExceptionForDuplicateKey(key); - } - - result[key] = new KeyedItemInfo(existingEntry.OldIndex, newStartIndex); - } - } - - newStartIndex = NextSiblingIndex(frame, newStartIndex); - } - - return result; - } - - private static void ThrowExceptionForDuplicateKey(object key) - { - throw new InvalidOperationException($"More than one sibling has the same key value, '{key}'. Key values must be unique."); - } - - private static object KeyValue(ref RenderTreeFrame frame) - { - switch (frame.FrameType) - { - case RenderTreeFrameType.Element: - return frame.ElementKey; - case RenderTreeFrameType.Component: - return frame.ComponentKey; - default: - return null; - } - } - - // Handles the diff for attribute nodes only - this invariant is enforced by the caller. - // - // The diff for attributes is different because we allow attributes to appear in any order. - // Put another way, the attributes list of an element or component is *conceptually* - // unordered. This is a case where we can produce a more minimal diff by avoiding - // non-meaningful reorderings of attributes. - private static void AppendAttributeDiffEntriesForRange( - ref DiffContext diffContext, - int oldStartIndex, int oldEndIndexExcl, - int newStartIndex, int newEndIndexExcl) - { - // The overhead of the dictionary used by AppendAttributeDiffEntriesForRangeSlow is - // significant, so we want to try and do a merge-join if possible, but fall back to - // a hash-join if not. We'll do a merge join until we hit a case we can't handle and - // then fall back to the slow path. - // - // Also since duplicate attributes are not legal, we don't need to care about loops or - // the more complicated scenarios handled by AppendDiffEntriesForRange. - // - // We also assume that we won't see an attribute occur with different sequence numbers - // in the old and new sequences. It will be handled correct, but will generate a suboptimal - // diff. - var hasMoreOld = oldEndIndexExcl > oldStartIndex; - var hasMoreNew = newEndIndexExcl > newStartIndex; - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - - while (hasMoreOld || hasMoreNew) - { - var oldSeq = hasMoreOld ? oldTree[oldStartIndex].Sequence : int.MaxValue; - var newSeq = hasMoreNew ? newTree[newStartIndex].Sequence : int.MaxValue; - var oldAttributeName = oldTree[oldStartIndex].AttributeName; - var newAttributeName = newTree[newStartIndex].AttributeName; - - if (oldSeq == newSeq && - string.Equals(oldAttributeName, newAttributeName, StringComparison.Ordinal)) - { - // These two attributes have the same sequence and name. Keep merging. - AppendDiffEntriesForAttributeFrame(ref diffContext, oldStartIndex, newStartIndex); - - oldStartIndex++; - newStartIndex++; - hasMoreOld = oldEndIndexExcl > oldStartIndex; - hasMoreNew = newEndIndexExcl > newStartIndex; - } - else if (oldSeq < newSeq) - { - if (oldSeq == SystemAddedAttributeSequenceNumber) - { - // This special sequence number means that we can't rely on the sequence numbers - // for matching and are forced to fall back on the dictionary-based join in order - // to produce an optimal diff. If we didn't we'd likely produce a diff that removes - // and then re-adds the same attribute. - // We use the special sequence number to signal it because it adds almost no cost - // to check for it only in this one case. - AppendAttributeDiffEntriesForRangeSlow( - ref diffContext, - oldStartIndex, oldEndIndexExcl, - newStartIndex, newEndIndexExcl); - return; - } - - // An attribute was removed compared to the old sequence. - RemoveOldFrame(ref diffContext, oldStartIndex); - - oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); - hasMoreOld = oldEndIndexExcl > oldStartIndex; - } - else if (oldSeq > newSeq) - { - // An attribute was added compared to the new sequence. - InsertNewFrame(ref diffContext, newStartIndex); - - newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); - hasMoreNew = newEndIndexExcl > newStartIndex; - } - else - { - // These two attributes have the same sequence and different names. This is - // a failure case for merge-join, fall back to the slow path. - AppendAttributeDiffEntriesForRangeSlow( - ref diffContext, - oldStartIndex, oldEndIndexExcl, - newStartIndex, newEndIndexExcl); - return; - } - } - } - - private static void AppendAttributeDiffEntriesForRangeSlow( - ref DiffContext diffContext, - int oldStartIndex, int oldEndIndexExcl, - int newStartIndex, int newEndIndexExcl) - { - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - - // Slow version of AppendAttributeDiffEntriesForRange that uses a dictionary. - // Algorithm: - // - // 1. iterate through the 'new' tree and add all attributes to the attributes set - // 2. iterate through the 'old' tree, removing matching attributes from set, and diffing - // 3. iterate through the remaining attributes in the set and add them - for (var i = newStartIndex; i < newEndIndexExcl; i++) - { - diffContext.AttributeDiffSet[newTree[i].AttributeName] = i; - } - - for (var i = oldStartIndex; i < oldEndIndexExcl; i++) - { - var oldName = oldTree[i].AttributeName; - if (diffContext.AttributeDiffSet.TryGetValue(oldName, out var matchIndex)) - { - // Has a match in the new tree, look for a diff - AppendDiffEntriesForAttributeFrame(ref diffContext, i, matchIndex); - diffContext.AttributeDiffSet.Remove(oldName); - } - else - { - // No match in the new tree, remove old attribute - RemoveOldFrame(ref diffContext, i); - } - } - - foreach (var kvp in diffContext.AttributeDiffSet) - { - // No match in the old tree - InsertNewFrame(ref diffContext, kvp.Value); - } - - // We should have processed any additions at this point. Reset for the next batch. - diffContext.AttributeDiffSet.Clear(); - } - - private static void UpdateRetainedChildComponent( - ref DiffContext diffContext, - int oldComponentIndex, - int newComponentIndex) - { - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - ref var oldComponentFrame = ref oldTree[oldComponentIndex]; - ref var newComponentFrame = ref newTree[newComponentIndex]; - var componentState = oldComponentFrame.ComponentState; - - // Preserve the actual componentInstance - newComponentFrame = newComponentFrame.WithComponent(componentState); - - // As an important rendering optimization, we want to skip parameter update - // notifications if we know for sure they haven't changed/mutated. The - // "MayHaveChangedSince" logic is conservative, in that it returns true if - // any parameter is of a type we don't know is immutable. In this case - // we call SetParameters and it's up to the recipient to implement - // whatever change-detection logic they want. Currently we only supply the new - // set of parameters and assume the recipient has enough info to do whatever - // comparisons it wants with the old values. Later we could choose to pass the - // old parameter values if we wanted. By default, components always rerender - // after any SetParameters call, which is safe but now always optimal for perf. - var oldParameters = new ParameterView(ParameterViewLifetime.Unbound, oldTree, oldComponentIndex); - var newParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder); - var newParameters = new ParameterView(newParametersLifetime, newTree, newComponentIndex); - if (!newParameters.DefinitelyEquals(oldParameters)) - { - componentState.SetDirectParameters(newParameters); - } - } - - private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex) - { - switch (frame.FrameType) - { - case RenderTreeFrameType.Component: - return frameIndex + frame.ComponentSubtreeLength; - case RenderTreeFrameType.Element: - return frameIndex + frame.ElementSubtreeLength; - case RenderTreeFrameType.Region: - return frameIndex + frame.RegionSubtreeLength; - default: - return frameIndex + 1; - } - } - - private static void AppendDiffEntriesForFramesWithSameSequence( - ref DiffContext diffContext, - int oldFrameIndex, - int newFrameIndex) - { - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - ref var oldFrame = ref oldTree[oldFrameIndex]; - ref var newFrame = ref newTree[newFrameIndex]; - - // This can't happen for sequence-matched frames from .razor components, but it can happen if you write your - // builder logic manually or if two dissimilar frames matched by key. Treat as completely unrelated. - var newFrameType = newFrame.FrameType; - if (oldFrame.FrameType != newFrameType) - { - InsertNewFrame(ref diffContext, newFrameIndex); - RemoveOldFrame(ref diffContext, oldFrameIndex); - return; - } - - // We can assume that the old and new frames are of the same type, because they correspond - // to the same sequence number (and if not, the behaviour is undefined). - // TODO: Consider supporting dissimilar types at same sequence for custom IComponent implementations. - // It should only be a matter of calling RemoveOldFrame+InsertNewFrame - switch (newFrameType) - { - case RenderTreeFrameType.Text: - { - var oldText = oldFrame.TextContent; - var newText = newFrame.TextContent; - if (!string.Equals(oldText, newText, StringComparison.Ordinal)) - { - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame); - diffContext.Edits.Append(RenderTreeEdit.UpdateText(diffContext.SiblingIndex, referenceFrameIndex)); - } - diffContext.SiblingIndex++; - break; - } - - case RenderTreeFrameType.Markup: - { - var oldMarkup = oldFrame.MarkupContent; - var newMarkup = newFrame.MarkupContent; - if (!string.Equals(oldMarkup, newMarkup, StringComparison.Ordinal)) - { - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame); - diffContext.Edits.Append(RenderTreeEdit.UpdateMarkup(diffContext.SiblingIndex, referenceFrameIndex)); - } - diffContext.SiblingIndex++; - break; - } - - case RenderTreeFrameType.Element: - { - var oldElementName = oldFrame.ElementName; - var newElementName = newFrame.ElementName; - if (string.Equals(oldElementName, newElementName, StringComparison.Ordinal)) - { - var oldFrameAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldFrameIndex); - var newFrameAttributesEndIndexExcl = GetAttributesEndIndexExclusive(newTree, newFrameIndex); - - // Diff the attributes - AppendAttributeDiffEntriesForRange( - ref diffContext, - oldFrameIndex + 1, oldFrameAttributesEndIndexExcl, - newFrameIndex + 1, newFrameAttributesEndIndexExcl); - - // Diff the children - var oldFrameChildrenEndIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLength; - var newFrameChildrenEndIndexExcl = newFrameIndex + newFrame.ElementSubtreeLength; - var hasChildrenToProcess = - oldFrameChildrenEndIndexExcl > oldFrameAttributesEndIndexExcl || - newFrameChildrenEndIndexExcl > newFrameAttributesEndIndexExcl; - if (hasChildrenToProcess) - { - diffContext.Edits.Append(RenderTreeEdit.StepIn(diffContext.SiblingIndex)); - var prevSiblingIndex = diffContext.SiblingIndex; - diffContext.SiblingIndex = 0; - AppendDiffEntriesForRange( - ref diffContext, - oldFrameAttributesEndIndexExcl, oldFrameChildrenEndIndexExcl, - newFrameAttributesEndIndexExcl, newFrameChildrenEndIndexExcl); - AppendStepOut(ref diffContext); - diffContext.SiblingIndex = prevSiblingIndex + 1; - } - else - { - diffContext.SiblingIndex++; - } - } - else - { - // Elements with different names are treated as completely unrelated - RemoveOldFrame(ref diffContext, oldFrameIndex); - InsertNewFrame(ref diffContext, newFrameIndex); - } - break; - } - - case RenderTreeFrameType.Region: - { - AppendDiffEntriesForRange( - ref diffContext, - oldFrameIndex + 1, oldFrameIndex + oldFrame.RegionSubtreeLength, - newFrameIndex + 1, newFrameIndex + newFrame.RegionSubtreeLength); - break; - } - - case RenderTreeFrameType.Component: - { - if (oldFrame.ComponentType == newFrame.ComponentType) - { - UpdateRetainedChildComponent( - ref diffContext, - oldFrameIndex, - newFrameIndex); - diffContext.SiblingIndex++; - } - else - { - // Child components of different types are treated as completely unrelated - RemoveOldFrame(ref diffContext, oldFrameIndex); - InsertNewFrame(ref diffContext, newFrameIndex); - } - break; - } - - case RenderTreeFrameType.ElementReferenceCapture: - { - // We could preserve the ElementReferenceCaptureId from the old frame to the new frame, - // and even call newFrame.ElementReferenceCaptureAction(id) each time in case it wants - // to do something different with the ID. However there's no known use case for - // that, so presently the rule is that for any given element, the reference - // capture action is only invoked once. - break; - } - - // We don't handle attributes here, they have their own diff logic. - // See AppendDiffEntriesForAttributeFrame - default: - throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}"); - } - } - - // This should only be called for attributes that have the same name. This is an - // invariant maintained by the callers. - private static void AppendDiffEntriesForAttributeFrame( - ref DiffContext diffContext, - int oldFrameIndex, - int newFrameIndex) - { - var oldTree = diffContext.OldTree; - var newTree = diffContext.NewTree; - ref var oldFrame = ref oldTree[oldFrameIndex]; - ref var newFrame = ref newTree[newFrameIndex]; - - // Using Equals to account for string comparisons, nulls, etc. - var valueChanged = !Equals(oldFrame.AttributeValue, newFrame.AttributeValue); - if (valueChanged) - { - InitializeNewAttributeFrame(ref diffContext, ref newFrame); - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame); - diffContext.Edits.Append(RenderTreeEdit.SetAttribute(diffContext.SiblingIndex, referenceFrameIndex)); - - // If we're replacing an old event handler ID with a new one, register the old one for disposal, - // plus keep track of the old->new chain until the old one is fully disposed - if (oldFrame.AttributeEventHandlerId > 0) - { - diffContext.Renderer.TrackReplacedEventHandlerId(oldFrame.AttributeEventHandlerId, newFrame.AttributeEventHandlerId); - diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerId); - } - } - else if (oldFrame.AttributeEventHandlerId > 0) - { - // Retain the event handler ID by copying the old frame over the new frame. - // this will prevent us from needing to dispose the old event handler - // since it was unchanged. - newFrame = oldFrame; - } - } - - private static void InsertNewFrame(ref DiffContext diffContext, int newFrameIndex) - { - var newTree = diffContext.NewTree; - ref var newFrame = ref newTree[newFrameIndex]; - switch (newFrame.FrameType) - { - case RenderTreeFrameType.Attribute: - { - InitializeNewAttributeFrame(ref diffContext, ref newFrame); - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame); - diffContext.Edits.Append(RenderTreeEdit.SetAttribute(diffContext.SiblingIndex, referenceFrameIndex)); - break; - } - case RenderTreeFrameType.Component: - case RenderTreeFrameType.Element: - { - InitializeNewSubtree(ref diffContext, newFrameIndex); - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newTree, newFrameIndex, newFrame.ElementSubtreeLength); - diffContext.Edits.Append(RenderTreeEdit.PrependFrame(diffContext.SiblingIndex, referenceFrameIndex)); - diffContext.SiblingIndex++; - break; - } - case RenderTreeFrameType.Region: - { - var regionChildFrameIndex = newFrameIndex + 1; - var regionChildFrameEndIndexExcl = newFrameIndex + newFrame.RegionSubtreeLength; - while (regionChildFrameIndex < regionChildFrameEndIndexExcl) - { - InsertNewFrame(ref diffContext, regionChildFrameIndex); - regionChildFrameIndex = NextSiblingIndex(newTree[regionChildFrameIndex], regionChildFrameIndex); - } - break; - } - case RenderTreeFrameType.Text: - case RenderTreeFrameType.Markup: - { - var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame); - diffContext.Edits.Append(RenderTreeEdit.PrependFrame(diffContext.SiblingIndex, referenceFrameIndex)); - diffContext.SiblingIndex++; - break; - } - case RenderTreeFrameType.ElementReferenceCapture: - { - InitializeNewElementReferenceCaptureFrame(ref diffContext, ref newFrame); - break; - } - case RenderTreeFrameType.ComponentReferenceCapture: - { - InitializeNewComponentReferenceCaptureFrame(ref diffContext, ref newFrame); - break; - } - default: - throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameType}"); - } - } - - private static void RemoveOldFrame(ref DiffContext diffContext, int oldFrameIndex) - { - var oldTree = diffContext.OldTree; - ref var oldFrame = ref oldTree[oldFrameIndex]; - switch (oldFrame.FrameType) - { - case RenderTreeFrameType.Attribute: - { - diffContext.Edits.Append(RenderTreeEdit.RemoveAttribute(diffContext.SiblingIndex, oldFrame.AttributeName)); - if (oldFrame.AttributeEventHandlerId > 0) - { - diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerId); - } - break; - } - case RenderTreeFrameType.Component: - case RenderTreeFrameType.Element: - { - var endIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLength; - DisposeFramesInRange(diffContext.BatchBuilder, oldTree, oldFrameIndex, endIndexExcl); - diffContext.Edits.Append(RenderTreeEdit.RemoveFrame(diffContext.SiblingIndex)); - break; - } - case RenderTreeFrameType.Region: - { - var regionChildFrameIndex = oldFrameIndex + 1; - var regionChildFrameEndIndexExcl = oldFrameIndex + oldFrame.RegionSubtreeLength; - while (regionChildFrameIndex < regionChildFrameEndIndexExcl) - { - RemoveOldFrame(ref diffContext, regionChildFrameIndex); - regionChildFrameIndex = NextSiblingIndex(oldTree[regionChildFrameIndex], regionChildFrameIndex); - } - break; - } - case RenderTreeFrameType.Text: - case RenderTreeFrameType.Markup: - { - diffContext.Edits.Append(RenderTreeEdit.RemoveFrame(diffContext.SiblingIndex)); - break; - } - default: - throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameType}"); - } - } - - private static int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex) - { - var descendantsEndIndexExcl = rootIndex + tree[rootIndex].ElementSubtreeLength; - var index = rootIndex + 1; - for (; index < descendantsEndIndexExcl; index++) - { - if (tree[index].FrameType != RenderTreeFrameType.Attribute) - { - break; - } - } - - return index; - } - - private static void AppendStepOut(ref DiffContext diffContext) - { - // If the preceding frame is a StepIn, then the StepOut cancels it out - var previousIndex = diffContext.Edits.Count - 1; - if (previousIndex >= 0 && diffContext.Edits.Buffer[previousIndex].Type == RenderTreeEditType.StepIn) - { - diffContext.Edits.RemoveLast(); - } - else - { - diffContext.Edits.Append(RenderTreeEdit.StepOut()); - } - } - - private static void InitializeNewSubtree(ref DiffContext diffContext, int frameIndex) - { - var frames = diffContext.NewTree; - var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLength; - for (var i = frameIndex; i < endIndexExcl; i++) - { - ref var frame = ref frames[i]; - switch (frame.FrameType) - { - case RenderTreeFrameType.Component: - InitializeNewComponentFrame(ref diffContext, i); - break; - case RenderTreeFrameType.Attribute: - InitializeNewAttributeFrame(ref diffContext, ref frame); - break; - case RenderTreeFrameType.ElementReferenceCapture: - InitializeNewElementReferenceCaptureFrame(ref diffContext, ref frame); - break; - case RenderTreeFrameType.ComponentReferenceCapture: - InitializeNewComponentReferenceCaptureFrame(ref diffContext, ref frame); - break; - } - } - } - - private static void InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex) - { - var frames = diffContext.NewTree; - ref var frame = ref frames[frameIndex]; - - if (frame.ComponentState != null) - { - throw new InvalidOperationException($"Child component already exists during {nameof(InitializeNewComponentFrame)}"); - } - - var parentComponentId = diffContext.ComponentId; - diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame, parentComponentId); - var childComponentState = frame.ComponentState; - - // Set initial parameters - var initialParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder); - var initialParameters = new ParameterView(initialParametersLifetime, frames, frameIndex); - childComponentState.SetDirectParameters(initialParameters); - } - - private static void InitializeNewAttributeFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) - { - // Any attribute with an event handler id will be callable via DOM events - // - // We're following a simple heuristic here that's reflected in the ts runtime - // based on the common usage of attributes for DOM events. - if ((newFrame.AttributeValue is MulticastDelegate || newFrame.AttributeValue is EventCallback) && - newFrame.AttributeName.Length >= 3 && - newFrame.AttributeName.StartsWith("on")) - { - diffContext.Renderer.AssignEventHandlerId(ref newFrame); - } - } - - private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) - { - var newElementReference = ElementReference.CreateWithUniqueId(); - newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id); - newFrame.ElementReferenceCaptureAction(newElementReference); - } - - private static void InitializeNewComponentReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) - { - ref var parentFrame = ref diffContext.NewTree[newFrame.ComponentReferenceCaptureParentFrameIndex]; - if (parentFrame.FrameType != RenderTreeFrameType.Component) - { - // Should never happen, but will help with diagnosis if it does - throw new InvalidOperationException($"{nameof(RenderTreeFrameType.ComponentReferenceCapture)} frame references invalid parent index."); - } - - var componentInstance = parentFrame.Component; - if (componentInstance == null) - { - // Should never happen, but will help with diagnosis if it does - throw new InvalidOperationException($"Trying to initialize {nameof(RenderTreeFrameType.ComponentReferenceCapture)} frame before parent component was assigned."); - } - - newFrame.ComponentReferenceCaptureAction(componentInstance); - } - - private static void DisposeFramesInRange(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int startIndex, int endIndexExcl) - { - for (var i = startIndex; i < endIndexExcl; i++) - { - ref var frame = ref frames[i]; - if (frame.FrameType == RenderTreeFrameType.Component && frame.ComponentState != null) - { - batchBuilder.ComponentDisposalQueue.Enqueue(frame.ComponentId); - } - else if (frame.FrameType == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerId > 0) - { - batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerId); - } - } - } - - /// - /// Exists only so that the various methods in this class can call each other without - /// constantly building up long lists of parameters. Is private to this class, so the - /// fact that it's a mutable struct is manageable. - /// - /// Always pass by ref to avoid copying, and because the 'SiblingIndex' is mutable. - /// - private struct DiffContext - { - public readonly Renderer Renderer; - public readonly RenderBatchBuilder BatchBuilder; - public readonly RenderTreeFrame[] OldTree; - public readonly RenderTreeFrame[] NewTree; - public readonly ArrayBuilder Edits; - public readonly ArrayBuilder ReferenceFrames; - public readonly Dictionary AttributeDiffSet; - public readonly StackObjectPool> KeyedItemInfoDictionaryPool; - public readonly int ComponentId; - public int SiblingIndex; - - public DiffContext( - Renderer renderer, - RenderBatchBuilder batchBuilder, - int componentId, - RenderTreeFrame[] oldTree, - RenderTreeFrame[] newTree) - { - Renderer = renderer; - BatchBuilder = batchBuilder; - ComponentId = componentId; - OldTree = oldTree; - NewTree = newTree; - Edits = batchBuilder.EditsBuffer; - ReferenceFrames = batchBuilder.ReferenceFramesBuffer; - AttributeDiffSet = batchBuilder.AttributeDiffSet; - KeyedItemInfoDictionaryPool = batchBuilder.KeyedItemInfoDictionaryPool; - SiblingIndex = 0; - } - } - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeEdit.cs b/src/Components/Components/src/RenderTree/RenderTreeEdit.cs deleted file mode 100644 index 93b1dd9da605..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeEdit.cs +++ /dev/null @@ -1,111 +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.InteropServices; - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - // - // Represents a single edit operation on a component's render tree. - [StructLayout(LayoutKind.Explicit)] - public readonly struct RenderTreeEdit - { - /// - /// Gets the type of the edit operation. - /// - [FieldOffset(0)] public readonly RenderTreeEditType Type; - - /// - /// Gets the index of the sibling frame that the edit relates to. - /// - [FieldOffset(4)] public readonly int SiblingIndex; - - /// - /// Gets the index of related data in an associated render frames array. For example, if the - /// value is , gets the - /// index of the new frame data in an associated render tree. - /// - [FieldOffset(8)] public readonly int ReferenceFrameIndex; - - /// - /// If the value is , - /// gets the sibling index to which the frame should be moved. - /// - // NOTE: Other code relies on the assumption that ReferenceFrameIndex and - // MoveToSiblingIndex share a memory slot. If you change this, be sure to - // update affected usages of ReferenceFrameIndex. - [FieldOffset(8)] public readonly int MoveToSiblingIndex; - - /// - /// If the value is , - /// gets the name of the attribute that is being removed. - /// - [FieldOffset(16)] public readonly string RemovedAttributeName; - - private RenderTreeEdit(RenderTreeEditType type) : this() - { - Type = type; - } - - private RenderTreeEdit(RenderTreeEditType type, int siblingIndex) : this() - { - Type = type; - SiblingIndex = siblingIndex; - } - - private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, int referenceFrameOrMoveToSiblingIndex) : this() - { - Type = type; - SiblingIndex = siblingIndex; - - // MoveToSiblingIndex is stored in the same slot as ReferenceFrameIndex, - // so assigning to either one is equivalent - ReferenceFrameIndex = referenceFrameOrMoveToSiblingIndex; - } - - private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, string removedAttributeName) : this() - { - Type = type; - SiblingIndex = siblingIndex; - RemovedAttributeName = removedAttributeName; - } - - internal static RenderTreeEdit RemoveFrame(int siblingIndex) - => new RenderTreeEdit(RenderTreeEditType.RemoveFrame, siblingIndex); - - internal static RenderTreeEdit PrependFrame(int siblingIndex, int referenceFrameIndex) - => new RenderTreeEdit(RenderTreeEditType.PrependFrame, siblingIndex, referenceFrameIndex); - - internal static RenderTreeEdit UpdateText(int siblingIndex, int referenceFrameIndex) - => new RenderTreeEdit(RenderTreeEditType.UpdateText, siblingIndex, referenceFrameIndex); - - internal static RenderTreeEdit UpdateMarkup(int siblingIndex, int referenceFrameIndex) - => new RenderTreeEdit(RenderTreeEditType.UpdateMarkup, siblingIndex, referenceFrameIndex); - - internal static RenderTreeEdit SetAttribute(int siblingIndex, int referenceFrameIndex) - => new RenderTreeEdit(RenderTreeEditType.SetAttribute, siblingIndex, referenceFrameIndex); - - internal static RenderTreeEdit RemoveAttribute(int siblingIndex, string name) - => new RenderTreeEdit(RenderTreeEditType.RemoveAttribute, siblingIndex, name); - - internal static RenderTreeEdit StepIn(int siblingIndex) - => new RenderTreeEdit(RenderTreeEditType.StepIn, siblingIndex); - - internal static RenderTreeEdit StepOut() - => new RenderTreeEdit(RenderTreeEditType.StepOut); - - internal static RenderTreeEdit PermutationListEntry(int fromSiblingIndex, int toSiblingIndex) - => new RenderTreeEdit(RenderTreeEditType.PermutationListEntry, fromSiblingIndex, toSiblingIndex); - - internal static RenderTreeEdit PermutationListEnd() - => new RenderTreeEdit(RenderTreeEditType.PermutationListEnd); - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeEditType.cs b/src/Components/Components/src/RenderTree/RenderTreeEditType.cs deleted file mode 100644 index f3d48172fb71..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeEditType.cs +++ /dev/null @@ -1,75 +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. - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - // - //Describes the type of a render tree edit operation. - public enum RenderTreeEditType: int - { - /// - /// Indicates that a new frame should be inserted before the specified tree frame. - /// - PrependFrame = 1, - - /// - /// Indicates that the specified tree frame should be removed. - /// - RemoveFrame = 2, - - /// - /// Indicates that an attribute value should be applied to the specified frame. - /// This may be a change to an existing attribute, or the addition of a new attribute. - /// - SetAttribute = 3, - - /// - /// Indicates that a named attribute should be removed from the specified frame. - /// - RemoveAttribute = 4, - - /// - /// Indicates that the text content of the specified frame (which must be a text frame) - /// should be updated. - /// - UpdateText = 5, - - /// - /// Indicates that the edit position should move inside the specified frame. - /// - StepIn = 6, - - /// - /// Indicates that there are no further edit operations on the current frame, and the - /// edit position should move back to the parent frame. - /// - StepOut = 7, - - /// - /// Indicates that the markup content of the specified frame (which must be a markup frame) - /// should be updated. - /// - UpdateMarkup = 8, - - /// - /// An entry in a sparse permutation list. That is, a list of old indices with - /// corresponding new indices, which altogether describe a valid permutation of - /// the children at the current edit position. - /// - PermutationListEntry = 9, - - /// - /// Indicates that the preceding series of entries - /// is now complete. - /// - PermutationListEnd = 10, - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs b/src/Components/Components/src/RenderTree/RenderTreeFrame.cs deleted file mode 100644 index c9a358c698b9..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs +++ /dev/null @@ -1,406 +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.Runtime.InteropServices; -#if !IGNITOR -using Microsoft.AspNetCore.Components.Rendering; -#endif - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - // - // Represents an entry in a tree of user interface (UI) items. - [StructLayout(LayoutKind.Explicit, Pack = 4)] - public readonly struct RenderTreeFrame - { - // Note that the struct layout has to be valid in both 32-bit and 64-bit runtime platforms, - // which means that all reference-type fields need to take up 8 bytes (except for the last - // one, which will be sized as either 4 or 8 bytes depending on the runtime platform). - - // Although each frame type uses the slots for different purposes, the runtime does not - // allow reference type slots to overlap with each other or with value-type slots. - // Here's the current layout: - // - // Offset Type - // ------ ---- - // 0-3 Int32 (sequence number) - // 4-5 Int16 (frame type) - // 6-15 Value types (usage varies by frame type) - // 16-23 Reference type (usage varies by frame type) - // 24-31 Reference type (usage varies by frame type) - // 32-39 Reference type (usage varies by frame type) - // - // On Mono WebAssembly, because it's 32-bit, the final slot occupies bytes 32-35, - // so the struct length is only 36. - - // -------------------------------------------------------------------------------- - // Common - // -------------------------------------------------------------------------------- - - /// - /// Gets the sequence number of the frame. Sequence numbers indicate the relative source - /// positions of the instructions that inserted the frames. Sequence numbers are only - /// comparable within the same sequence (typically, the same source method). - /// - [FieldOffset(0)] public readonly int Sequence; - - /// - /// Describes the type of this frame. - /// - [FieldOffset(4)] public readonly RenderTreeFrameType FrameType; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Element - // -------------------------------------------------------------------------------- - - /// - /// If the property equals - /// gets the number of frames in the subtree for which this frame is the root. - /// The value is zero if the frame has not yet been closed. - /// - [FieldOffset(8)] public readonly int ElementSubtreeLength; - - /// - /// If the property equals , - /// gets a name representing the type of the element. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly string ElementName; - - /// - /// If the property equals , - /// gets the element's diffing key, or null if none was specified. - /// - [FieldOffset(24)] public readonly object ElementKey; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Text - // -------------------------------------------------------------------------------- - - /// - /// If the property equals , - /// gets the content of the text frame. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly string TextContent; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Attribute - // -------------------------------------------------------------------------------- - - /// - /// If the property equals - /// gets the ID of the corresponding event handler, if any. - /// - [FieldOffset(8)] public readonly ulong AttributeEventHandlerId; - - /// - /// If the property equals , - /// gets the attribute name. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly string AttributeName; - - /// - /// If the property equals , - /// gets the attribute value. Otherwise, the value is undefined. - /// - [FieldOffset(24)] public readonly object AttributeValue; - - /// - /// If the property equals , - /// and the attribute represents an event handler, gets the name of another attribute whose value - /// can be updated to represent the UI state prior to executing the event handler. This is - /// primarily used in two-way bindings. - /// - [FieldOffset(32)] public readonly string AttributeEventUpdatesAttributeName; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Component - // -------------------------------------------------------------------------------- - - /// - /// If the property equals - /// gets the number of frames in the subtree for which this frame is the root. - /// The value is zero if the frame has not yet been closed. - /// - [FieldOffset(8)] public readonly int ComponentSubtreeLength; - - /// - /// If the property equals , - /// gets the child component instance identifier. - /// - [FieldOffset(12)] public readonly int ComponentId; - - /// - /// If the property equals , - /// gets the type of the child component. - /// - [FieldOffset(16)] public readonly Type ComponentType; - - /// - /// If the property equals , - /// gets the child component state object. Otherwise, the value is undefined. - /// - [FieldOffset(24)] internal readonly ComponentState ComponentState; - - /// - /// If the property equals , - /// gets the component's diffing key, or null if none was specified. - /// - [FieldOffset(32)] public readonly object ComponentKey; - - /// - /// If the property equals , - /// gets the child component instance. Otherwise, the value is undefined. - /// - public IComponent Component => ComponentState?.Component; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Region - // -------------------------------------------------------------------------------- - - /// - /// If the property equals - /// gets the number of frames in the subtree for which this frame is the root. - /// The value is zero if the frame has not yet been closed. - /// - [FieldOffset(8)] public readonly int RegionSubtreeLength; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.ElementReferenceCapture - // -------------------------------------------------------------------------------- - - /// - /// If the property equals , - /// gets the ID of the reference capture. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly string ElementReferenceCaptureId; - - /// - /// If the property equals , - /// gets the action that writes the reference to its target. Otherwise, the value is undefined. - /// - [FieldOffset(24)] public readonly Action ElementReferenceCaptureAction; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.ComponentReferenceCapture - // -------------------------------------------------------------------------------- - - /// - /// If the property equals , - /// gets the index of the parent frame representing the component being captured. Otherwise, the value is undefined. - /// WARNING: This index can only be used in the context of the frame's original render tree. If the frame is - /// copied elsewhere, such as to the ReferenceFrames buffer of a RenderTreeDiff, then the index will - /// not relate to entries in that other buffer. - /// Currently there's no scenario where this matters, but if there was, we could change all of the subtree - /// initialization logic in RenderTreeDiffBuilder to walk the frames hierarchically, then it would know - /// the parent index at the point where it wants to initialize the ComponentReferenceCapture frame. - /// - [FieldOffset(8)] public readonly int ComponentReferenceCaptureParentFrameIndex; - - /// - /// If the property equals , - /// gets the action that writes the reference to its target. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly Action ComponentReferenceCaptureAction; - - // -------------------------------------------------------------------------------- - // RenderTreeFrameType.Markup - // -------------------------------------------------------------------------------- - - /// - /// If the property equals , - /// gets the content of the markup frame. Otherwise, the value is undefined. - /// - [FieldOffset(16)] public readonly string MarkupContent; - - // Element constructor - private RenderTreeFrame(int sequence, int elementSubtreeLength, string elementName, object elementKey) - : this() - { - Sequence = sequence; - FrameType = RenderTreeFrameType.Element; - ElementSubtreeLength = elementSubtreeLength; - ElementName = elementName; - ElementKey = elementKey; - } - - // Component constructor - private RenderTreeFrame(int sequence, int componentSubtreeLength, Type componentType, ComponentState componentState, object componentKey) - : this() - { - Sequence = sequence; - FrameType = RenderTreeFrameType.Component; - ComponentSubtreeLength = componentSubtreeLength; - ComponentType = componentType; - ComponentKey = componentKey; - - if (componentState != null) - { - ComponentState = componentState; - ComponentId = componentState.ComponentId; - } - } - - // Region constructor - private RenderTreeFrame(int sequence, int regionSubtreeLength) - : this() - { - Sequence = sequence; - FrameType = RenderTreeFrameType.Region; - RegionSubtreeLength = regionSubtreeLength; - } - - // Text/markup constructor - private RenderTreeFrame(int sequence, bool isMarkup, string textOrMarkup) - : this() - { - Sequence = sequence; - if (isMarkup) - { - FrameType = RenderTreeFrameType.Markup; - MarkupContent = textOrMarkup; - } - else - { - FrameType = RenderTreeFrameType.Text; - TextContent = textOrMarkup; - } - } - - // Attribute constructor - private RenderTreeFrame(int sequence, string attributeName, object attributeValue, ulong attributeEventHandlerId, string attributeEventUpdatesAttributeName) - : this() - { - FrameType = RenderTreeFrameType.Attribute; - Sequence = sequence; - AttributeName = attributeName; - AttributeValue = attributeValue; - AttributeEventHandlerId = attributeEventHandlerId; - AttributeEventUpdatesAttributeName = attributeEventUpdatesAttributeName; - } - - // Element reference capture constructor - private RenderTreeFrame(int sequence, Action elementReferenceCaptureAction, string elementReferenceCaptureId) - : this() - { - FrameType = RenderTreeFrameType.ElementReferenceCapture; - Sequence = sequence; - ElementReferenceCaptureAction = elementReferenceCaptureAction; - ElementReferenceCaptureId = elementReferenceCaptureId; - } - - // Component reference capture constructor - private RenderTreeFrame(int sequence, Action componentReferenceCaptureAction, int parentFrameIndex) - : this() - { - FrameType = RenderTreeFrameType.ComponentReferenceCapture; - Sequence = sequence; - ComponentReferenceCaptureAction = componentReferenceCaptureAction; - ComponentReferenceCaptureParentFrameIndex = parentFrameIndex; - } - - internal static RenderTreeFrame Element(int sequence, string elementName) - => new RenderTreeFrame(sequence, elementSubtreeLength: 0, elementName, null); - - internal static RenderTreeFrame Text(int sequence, string textContent) - => new RenderTreeFrame(sequence, isMarkup: false, textOrMarkup: textContent); - - internal static RenderTreeFrame Markup(int sequence, string markupContent) - => new RenderTreeFrame(sequence, isMarkup: true, textOrMarkup: markupContent); - - internal static RenderTreeFrame Attribute(int sequence, string name, object value) - => new RenderTreeFrame(sequence, attributeName: name, attributeValue: value, attributeEventHandlerId: 0, attributeEventUpdatesAttributeName: null); - - internal static RenderTreeFrame ChildComponent(int sequence, Type componentType) - => new RenderTreeFrame(sequence, componentSubtreeLength: 0, componentType, null, null); - - internal static RenderTreeFrame PlaceholderChildComponentWithSubtreeLength(int subtreeLength) - => new RenderTreeFrame(0, componentSubtreeLength: subtreeLength, typeof(IComponent), null, null); - - internal static RenderTreeFrame Region(int sequence) - => new RenderTreeFrame(sequence, regionSubtreeLength: 0); - - internal static RenderTreeFrame ElementReferenceCapture(int sequence, Action elementReferenceCaptureAction) - => new RenderTreeFrame(sequence, elementReferenceCaptureAction: elementReferenceCaptureAction, elementReferenceCaptureId: null); - - internal static RenderTreeFrame ComponentReferenceCapture(int sequence, Action componentReferenceCaptureAction, int parentFrameIndex) - => new RenderTreeFrame(sequence, componentReferenceCaptureAction: componentReferenceCaptureAction, parentFrameIndex: parentFrameIndex); - - internal RenderTreeFrame WithElementSubtreeLength(int elementSubtreeLength) - => new RenderTreeFrame(Sequence, elementSubtreeLength: elementSubtreeLength, ElementName, ElementKey); - - internal RenderTreeFrame WithComponentSubtreeLength(int componentSubtreeLength) - => new RenderTreeFrame(Sequence, componentSubtreeLength: componentSubtreeLength, ComponentType, ComponentState, ComponentKey); - - internal RenderTreeFrame WithAttributeSequence(int sequence) - => new RenderTreeFrame(sequence, attributeName: AttributeName, AttributeValue, AttributeEventHandlerId, AttributeEventUpdatesAttributeName); - - internal RenderTreeFrame WithComponent(ComponentState componentState) - => new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, componentState, ComponentKey); - - internal RenderTreeFrame WithAttributeEventHandlerId(ulong eventHandlerId) - => new RenderTreeFrame(Sequence, attributeName: AttributeName, AttributeValue, eventHandlerId, AttributeEventUpdatesAttributeName); - - internal RenderTreeFrame WithAttributeValue(object attributeValue) - => new RenderTreeFrame(Sequence, attributeName: AttributeName, attributeValue, AttributeEventHandlerId, AttributeEventUpdatesAttributeName); - - internal RenderTreeFrame WithAttributeEventUpdatesAttributeName(string attributeUpdatesAttributeName) - => new RenderTreeFrame(Sequence, attributeName: AttributeName, AttributeValue, AttributeEventHandlerId, attributeUpdatesAttributeName); - - internal RenderTreeFrame WithRegionSubtreeLength(int regionSubtreeLength) - => new RenderTreeFrame(Sequence, regionSubtreeLength: regionSubtreeLength); - - internal RenderTreeFrame WithElementReferenceCaptureId(string elementReferenceCaptureId) - => new RenderTreeFrame(Sequence, elementReferenceCaptureAction: ElementReferenceCaptureAction, elementReferenceCaptureId); - - internal RenderTreeFrame WithElementKey(object elementKey) - => new RenderTreeFrame(Sequence, elementSubtreeLength: ElementSubtreeLength, ElementName, elementKey); - - internal RenderTreeFrame WithComponentKey(object componentKey) - => new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, ComponentState, componentKey); - - /// - // Just to be nice for debugging and unit tests. - public override string ToString() - { - switch (FrameType) - { - case RenderTreeFrameType.Attribute: - return $"Attribute: (seq={Sequence}, id={AttributeEventHandlerId}) '{AttributeName}'='{AttributeValue}'"; - - case RenderTreeFrameType.Component: - return $"Component: (seq={Sequence}, key={ComponentKey ?? "(none)"}, len={ComponentSubtreeLength}) {ComponentType}"; - - case RenderTreeFrameType.Element: - return $"Element: (seq={Sequence}, key={ElementKey ?? "(none)"}, len={ElementSubtreeLength}) {ElementName}"; - - case RenderTreeFrameType.Region: - return $"Region: (seq={Sequence}, len={RegionSubtreeLength})"; - - case RenderTreeFrameType.Text: - return $"Text: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContent)}"; - - case RenderTreeFrameType.Markup: - return $"Markup: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContent)}"; - - case RenderTreeFrameType.ElementReferenceCapture: - return $"ElementReferenceCapture: (seq={Sequence}, len=n/a) {ElementReferenceCaptureAction}"; - } - - return base.ToString(); - } - - private static string EscapeNewlines(string text) - { - return text.Replace("\n", "\\n").Replace("\r\n", "\\r\\n"); - } - } -} diff --git a/src/Components/Components/src/RenderTree/RenderTreeFrameType.cs b/src/Components/Components/src/RenderTree/RenderTreeFrameType.cs deleted file mode 100644 index e73119e03800..000000000000 --- a/src/Components/Components/src/RenderTree/RenderTreeFrameType.cs +++ /dev/null @@ -1,66 +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. - -#if IGNITOR -namespace Ignitor -#else -namespace Microsoft.AspNetCore.Components.RenderTree -#endif -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in future release. - /// - // - // Describes the type of a . - public enum RenderTreeFrameType: short - { - /// - /// Used only for unintialized frames. - /// - None = 0, - - /// - /// Represents a container for other frames. - /// - Element = 1, - - /// - /// Represents text content. - /// - Text = 2, - - /// - /// Represents a key-value pair associated with another . - /// - Attribute = 3, - - /// - /// Represents a child component. - /// - Component = 4, - - /// - /// Defines the boundary around range of sibling frames that should be treated as an - /// unsplittable group for the purposes of diffing. This is typically used when appending - /// a tree fragment generated by external code, because the sequence numbers in that tree - /// fragment are not comparable to sequence numbers outside it. - /// - Region = 5, - - /// - /// Represents an instruction to capture or update a reference to the parent element. - /// - ElementReferenceCapture = 6, - - /// - /// Represents an instruction to capture or update a reference to the parent component. - /// - ComponentReferenceCapture = 7, - - /// - /// Represents a block of markup content. - /// - Markup = 8, - } -} diff --git a/src/Components/Components/src/RenderTree/Renderer.Log.cs b/src/Components/Components/src/RenderTree/Renderer.Log.cs deleted file mode 100644 index 9362ecf4f5e9..000000000000 --- a/src/Components/Components/src/RenderTree/Renderer.Log.cs +++ /dev/null @@ -1,66 +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 Microsoft.AspNetCore.Components.Rendering; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - public abstract partial class Renderer - { - internal static class Log - { - private static readonly Action _initializingChildComponent = - LoggerMessage.Define(LogLevel.Debug, new EventId(1, "InitializingChildComponent"), "Initializing component {ComponentId} ({ComponentType}) as child of {ParentComponentId} ({ParentComponentId})"); - - private static readonly Action _initializingRootComponent = - LoggerMessage.Define(LogLevel.Debug, new EventId(2, "InitializingRootComponent"), "Initializing root component {ComponentId} ({ComponentType})"); - - private static readonly Action _renderingComponent = - LoggerMessage.Define(LogLevel.Debug, new EventId(3, "RenderingComponent"), "Rendering component {ComponentId} of type {ComponentType}"); - - private static readonly Action _disposingComponent = - LoggerMessage.Define(LogLevel.Debug, new EventId(4, "DisposingComponent"), "Disposing component {ComponentId} of type {ComponentType}"); - - private static readonly Action _handlingEvent = - LoggerMessage.Define(LogLevel.Debug, new EventId(5, "HandlingEvent"), "Handling event {EventId} of type '{EventType}'"); - - public static void InitializingComponent(ILogger logger, ComponentState componentState, ComponentState parentComponentState) - { - if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations - { - if (parentComponentState == null) - { - _initializingRootComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null); - } - else - { - _initializingChildComponent(logger, componentState.ComponentId, componentState.Component.GetType(), parentComponentState.ComponentId, parentComponentState.Component.GetType(), null); - } - } - } - - public static void RenderingComponent(ILogger logger, ComponentState componentState) - { - if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations - { - _renderingComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null); - } - } - - public static void DisposingComponent(ILogger logger, ComponentState componentState) - { - if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations - { - _disposingComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null); - } - } - - public static void HandlingEvent(ILogger logger, ulong eventHandlerId, EventArgs eventArgs) - { - _handlingEvent(logger, eventHandlerId, eventArgs?.GetType().Name ?? "null", null); - } - } - } -} diff --git a/src/Components/Components/src/RenderTree/Renderer.cs b/src/Components/Components/src/RenderTree/Renderer.cs deleted file mode 100644 index 05cfb41abe24..000000000000 --- a/src/Components/Components/src/RenderTree/Renderer.cs +++ /dev/null @@ -1,737 +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.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - /// - /// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside - /// of the Blazor framework. These types will change in a future release. - /// - // - // Provides mechanisms for rendering hierarchies of instances, - // dispatching events to them, and notifying when the user interface is being updated. - public abstract partial class Renderer : IDisposable - { - private readonly IServiceProvider _serviceProvider; - private readonly Dictionary _componentStateById = new Dictionary(); - private readonly RenderBatchBuilder _batchBuilder = new RenderBatchBuilder(); - private readonly Dictionary _eventBindings = new Dictionary(); - private readonly Dictionary _eventHandlerIdReplacements = new Dictionary(); - private readonly ILogger _logger; - - private int _nextComponentId = 0; // TODO: change to 'long' when Mono .NET->JS interop supports it - private bool _isBatchInProgress; - private ulong _lastEventHandlerId; - private List _pendingTasks; - private bool _disposed; - - /// - /// Allows the caller to handle exceptions from the SynchronizationContext when one is available. - /// - public event UnhandledExceptionEventHandler UnhandledSynchronizationException - { - add - { - Dispatcher.UnhandledException += value; - } - remove - { - Dispatcher.UnhandledException -= value; - } - } - - /// - /// Constructs an instance of . - /// - /// The to be used when initializing components. - /// The . - public Renderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) - { - if (serviceProvider is null) - { - throw new ArgumentNullException(nameof(serviceProvider)); - } - - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _serviceProvider = serviceProvider; - _logger = loggerFactory.CreateLogger(); - } - - /// - /// Gets the associated with this . - /// - public abstract Dispatcher Dispatcher { get; } - - /// - /// Constructs a new component of the specified type. - /// - /// The type of the component to instantiate. - /// The component instance. - protected IComponent InstantiateComponent(Type componentType) - => ComponentFactory.Instance.InstantiateComponent(_serviceProvider, componentType); - - /// - /// Associates the with the , assigning - /// an identifier that is unique within the scope of the . - /// - /// The component. - /// The component's assigned identifier. - // Internal for unit testing - protected internal int AssignRootComponentId(IComponent component) - => AttachAndInitComponent(component, -1).ComponentId; - - /// - /// Gets the current render tree for a given component. - /// - /// The id for the component. - /// The representing the current render tree. - protected ArrayRange GetCurrentRenderTreeFrames(int componentId) => GetRequiredComponentState(componentId).CurrentRenderTree.GetFrames(); - - /// - /// Performs the first render for a root component, waiting for this component and all - /// children components to finish rendering in case there is any asynchronous work being - /// done by any of the components. After this, the root component - /// makes its own decisions about when to re-render, so there is no need to call - /// this more than once. - /// - /// The ID returned by . - /// - /// Rendering a root component is an asynchronous operation. Clients may choose to not await the returned task to - /// start, but not wait for the entire render to complete. - /// - protected Task RenderRootComponentAsync(int componentId) - { - return RenderRootComponentAsync(componentId, ParameterView.Empty); - } - - /// - /// Performs the first render for a root component, waiting for this component and all - /// children components to finish rendering in case there is any asynchronous work being - /// done by any of the components. After this, the root component - /// makes its own decisions about when to re-render, so there is no need to call - /// this more than once. - /// - /// The ID returned by . - /// The with the initial parameters to use for rendering. - /// - /// Rendering a root component is an asynchronous operation. Clients may choose to not await the returned task to - /// start, but not wait for the entire render to complete. - /// - protected async Task RenderRootComponentAsync(int componentId, ParameterView initialParameters) - { - if (Interlocked.CompareExchange(ref _pendingTasks, new List(), null) != null) - { - throw new InvalidOperationException("There is an ongoing rendering in progress."); - } - - // During the rendering process we keep a list of components performing work in _pendingTasks. - // _renderer.AddToPendingTasks will be called by ComponentState.SetDirectParameters to add the - // the Task produced by Component.SetParametersAsync to _pendingTasks in order to track the - // remaining work. - // During the synchronous rendering process we don't wait for the pending asynchronous - // work to finish as it will simply trigger new renders that will be handled afterwards. - // During the asynchronous rendering process we want to wait up untill al components have - // finished rendering so that we can produce the complete output. - var componentState = GetRequiredComponentState(componentId); - componentState.SetDirectParameters(initialParameters); - - try - { - await ProcessAsynchronousWork(); - Debug.Assert(_pendingTasks.Count == 0); - } - finally - { - _pendingTasks = null; - } - } - - /// - /// Allows derived types to handle exceptions during rendering. Defaults to rethrowing the original exception. - /// - /// The . - protected abstract void HandleException(Exception exception); - - private async Task ProcessAsynchronousWork() - { - // Child components SetParametersAsync are stored in the queue of pending tasks, - // which might trigger further renders. - while (_pendingTasks.Count > 0) - { - // Create a Task that represents the remaining ongoing work for the rendering process - var pendingWork = Task.WhenAll(_pendingTasks); - - // Clear all pending work. - _pendingTasks.Clear(); - - // new work might be added before we check again as a result of waiting for all - // the child components to finish executing SetParametersAsync - await pendingWork; - } - } - - private ComponentState AttachAndInitComponent(IComponent component, int parentComponentId) - { - var componentId = _nextComponentId++; - var parentComponentState = GetOptionalComponentState(parentComponentId); - var componentState = new ComponentState(this, componentId, component, parentComponentState); - Log.InitializingComponent(_logger, componentState, parentComponentState); - _componentStateById.Add(componentId, componentState); - component.Attach(new RenderHandle(this, componentId)); - return componentState; - } - - /// - /// Updates the visible UI. - /// - /// The changes to the UI since the previous call. - /// A to represent the UI update process. - protected abstract Task UpdateDisplayAsync(in RenderBatch renderBatch); - - /// - /// Notifies the renderer that an event has occurred. - /// - /// The value from the original event attribute. - /// Arguments to be passed to the event handler. - /// Information that the renderer can use to update the state of the existing render tree to match the UI. - /// - /// A which will complete once all asynchronous processing related to the event - /// has completed. - /// - public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs) - { - Dispatcher.AssertAccess(); - - if (!_eventBindings.TryGetValue(eventHandlerId, out var callback)) - { - throw new ArgumentException($"There is no event handler associated with this event. EventId: '{eventHandlerId}'.", nameof(eventHandlerId)); - } - - Log.HandlingEvent(_logger, eventHandlerId, eventArgs); - - if (fieldInfo != null) - { - var latestEquivalentEventHandlerId = FindLatestEventHandlerIdInChain(eventHandlerId); - UpdateRenderTreeToMatchClientState(latestEquivalentEventHandlerId, fieldInfo); - } - - Task task = null; - try - { - // The event handler might request multiple renders in sequence. Capture them - // all in a single batch. - _isBatchInProgress = true; - - task = callback.InvokeAsync(eventArgs); - } - catch (Exception e) - { - HandleException(e); - return Task.CompletedTask; - } - finally - { - _isBatchInProgress = false; - - // Since the task has yielded - process any queued rendering work before we return control - // to the caller. - ProcessPendingRender(); - } - - // Task completed synchronously or is still running. We already processed all of the rendering - // work that was queued so let our error handler deal with it. - return GetErrorHandledTask(task); - } - - internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId) - { - if (frame.FrameType != RenderTreeFrameType.Component) - { - throw new ArgumentException($"The frame's {nameof(RenderTreeFrame.FrameType)} property must equal {RenderTreeFrameType.Component}", nameof(frame)); - } - - if (frame.ComponentState != null) - { - throw new ArgumentException($"The frame already has a non-null component instance", nameof(frame)); - } - - var newComponent = InstantiateComponent(frame.ComponentType); - var newComponentState = AttachAndInitComponent(newComponent, parentComponentId); - frame = frame.WithComponent(newComponentState); - } - - internal void AddToPendingTasks(Task task) - { - switch (task == null ? TaskStatus.RanToCompletion : task.Status) - { - // If it's already completed synchronously, no need to add it to the list of - // pending Tasks as no further render (we already rerender synchronously) will. - // happen. - case TaskStatus.RanToCompletion: - case TaskStatus.Canceled: - break; - case TaskStatus.Faulted: - // We want to immediately handle exceptions if the task failed synchronously instead of - // waiting for it to throw later. This can happen if the task is produced by - // an 'async' state machine (the ones generated using async/await) where even - // the synchronous exceptions will get captured and converted into a faulted - // task. - HandleException(task.Exception.GetBaseException()); - break; - default: - // It's important to evaluate the following even if we're not going to use - // handledErrorTask below, because it has the side-effect of calling HandleException. - var handledErrorTask = GetErrorHandledTask(task); - - // The pendingTasks collection is only used during prerendering to track quiescence, - // so will be null at other times. - _pendingTasks?.Add(handledErrorTask); - - break; - } - } - - internal void AssignEventHandlerId(ref RenderTreeFrame frame) - { - var id = ++_lastEventHandlerId; - - if (frame.AttributeValue is EventCallback callback) - { - // We hit this case when a EventCallback object is produced that needs an explicit receiver. - // Common cases for this are "chained bind" or "chained event handler" when a component - // accepts a delegate as a parameter and then hooks it up to a DOM event. - // - // When that happens we intentionally box the EventCallback because we need to hold on to - // the receiver. - _eventBindings.Add(id, callback); - } - else if (frame.AttributeValue is MulticastDelegate @delegate) - { - // This is the common case for a delegate, where the receiver of the event - // is the same as delegate.Target. In this case since the receiver is implicit we can - // avoid boxing the EventCallback object and just re-hydrate it on the other side of the - // render tree. - _eventBindings.Add(id, new EventCallback(@delegate.Target as IHandleEvent, @delegate)); - } - - // NOTE: we do not to handle EventCallback here. EventCallback is only used when passing - // a callback to a component, and never when used to attaching a DOM event handler. - - frame = frame.WithAttributeEventHandlerId(id); - } - - /// - /// Schedules a render for the specified . Its display - /// will be populated using the specified . - /// - /// The ID of the component to render. - /// A that will supply the updated UI contents. - internal void AddToRenderQueue(int componentId, RenderFragment renderFragment) - { - Dispatcher.AssertAccess(); - - var componentState = GetOptionalComponentState(componentId); - if (componentState == null) - { - // If the component was already disposed, then its render handle trying to - // queue a render is a no-op. - return; - } - - _batchBuilder.ComponentRenderQueue.Enqueue( - new RenderQueueEntry(componentState, renderFragment)); - - if (!_isBatchInProgress) - { - ProcessPendingRender(); - } - } - - internal void TrackReplacedEventHandlerId(ulong oldEventHandlerId, ulong newEventHandlerId) - { - // Tracking the chain of old->new replacements allows us to interpret incoming EventFieldInfo - // values even if they refer to an event handler ID that's since been superseded. This is essential - // for tree patching to work in an async environment. - _eventHandlerIdReplacements.Add(oldEventHandlerId, newEventHandlerId); - } - - private ulong FindLatestEventHandlerIdInChain(ulong eventHandlerId) - { - while (_eventHandlerIdReplacements.TryGetValue(eventHandlerId, out var replacementEventHandlerId)) - { - eventHandlerId = replacementEventHandlerId; - } - - return eventHandlerId; - } - - private ComponentState GetRequiredComponentState(int componentId) - => _componentStateById.TryGetValue(componentId, out var componentState) - ? componentState - : throw new ArgumentException($"The renderer does not have a component with ID {componentId}."); - - private ComponentState GetOptionalComponentState(int componentId) - => _componentStateById.TryGetValue(componentId, out var componentState) - ? componentState - : null; - - /// - /// Processses pending renders requests from components if there are any. - /// - protected virtual void ProcessPendingRender() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(Renderer), "Cannot process pending renders after the renderer has been disposed."); - } - - ProcessRenderQueue(); - } - - private void ProcessRenderQueue() - { - Dispatcher.AssertAccess(); - - if (_isBatchInProgress) - { - throw new InvalidOperationException("Cannot start a batch when one is already in progress."); - } - - _isBatchInProgress = true; - var updateDisplayTask = Task.CompletedTask; - - try - { - if (_batchBuilder.ComponentRenderQueue.Count == 0) - { - return; - } - - // Process render queue until empty - while (_batchBuilder.ComponentRenderQueue.Count > 0) - { - var nextToRender = _batchBuilder.ComponentRenderQueue.Dequeue(); - RenderInExistingBatch(nextToRender); - } - - var batch = _batchBuilder.ToBatch(); - updateDisplayTask = UpdateDisplayAsync(batch); - - // Fire off the execution of OnAfterRenderAsync, but don't wait for it - // if there is async work to be done. - _ = InvokeRenderCompletedCalls(batch.UpdatedComponents, updateDisplayTask); - } - catch (Exception e) - { - // Ensure we catch errors while running the render functions of the components. - HandleException(e); - return; - } - finally - { - RemoveEventHandlerIds(_batchBuilder.DisposedEventHandlerIds.ToRange(), updateDisplayTask); - _batchBuilder.ClearStateForCurrentBatch(); - _isBatchInProgress = false; - } - - // An OnAfterRenderAsync callback might have queued more work synchronously. - // Note: we do *not* re-render implicitly after the OnAfterRenderAsync-returned - // task (that would be an infinite loop). We only render after an explicit render - // request (e.g., StateHasChanged()). - if (_batchBuilder.ComponentRenderQueue.Count > 0) - { - ProcessRenderQueue(); - } - } - - private Task InvokeRenderCompletedCalls(ArrayRange updatedComponents, Task updateDisplayTask) - { - if (updateDisplayTask.IsCanceled) - { - // The display update was canceled. - // This can be due to a timeout on the components server-side case, or the renderer being disposed. - - // The latter case is normal during prerendering, as the render never fully completes (the display never - // gets updated, no references get populated and JavaScript interop is not available) and we simply discard - // the renderer after producing the prerendered content. - return Task.CompletedTask; - } - if (updateDisplayTask.IsFaulted) - { - // The display update failed so we don't care any more about running on render completed - // fallbacks as the entire rendering process is going to be torn down. - HandleException(updateDisplayTask.Exception); - return Task.CompletedTask; - } - - if (!updateDisplayTask.IsCompleted) - { - var updatedComponentsId = new int[updatedComponents.Count]; - var updatedComponentsArray = updatedComponents.Array; - for (int i = 0; i < updatedComponentsId.Length; i++) - { - updatedComponentsId[i] = updatedComponentsArray[i].ComponentId; - } - - return InvokeRenderCompletedCallsAfterUpdateDisplayTask(updateDisplayTask, updatedComponentsId); - } - - List batch = null; - var array = updatedComponents.Array; - for (var i = 0; i < updatedComponents.Count; i++) - { - var componentState = GetOptionalComponentState(array[i].ComponentId); - if (componentState != null) - { - NotifyRenderCompleted(componentState, ref batch); - } - } - - return batch != null ? - Task.WhenAll(batch) : - Task.CompletedTask; - - } - - private async Task InvokeRenderCompletedCallsAfterUpdateDisplayTask( - Task updateDisplayTask, - int[] updatedComponents) - { - try - { - await updateDisplayTask; - } - catch // avoiding exception filters for AOT runtimes - { - if (updateDisplayTask.IsCanceled) - { - return; - } - - HandleException(updateDisplayTask.Exception); - return; - } - - List batch = null; - var array = updatedComponents; - for (var i = 0; i < updatedComponents.Length; i++) - { - var componentState = GetOptionalComponentState(array[i]); - if (componentState != null) - { - NotifyRenderCompleted(componentState, ref batch); - } - } - - var result = batch != null ? - Task.WhenAll(batch) : - Task.CompletedTask; - - await result; - } - - private void NotifyRenderCompleted(ComponentState state, ref List batch) - { - // The component might be rendered and disposed in the same batch (if its parent - // was rendered later in the batch, and removed the child from the tree). - // This can also happen between batches if the UI takes some time to update and within - // that time the component gets removed out of the tree because the parent chose not to - // render it in a later batch. - // In any of the two cases mentioned happens, OnAfterRenderAsync won't run but that is - // ok. - var task = state.NotifyRenderCompletedAsync(); - - // We want to avoid allocations per rendering. Avoid allocating a state machine or an accumulator - // unless we absolutely have to. - if (task.IsCompleted) - { - if (task.Status == TaskStatus.RanToCompletion || task.Status == TaskStatus.Canceled) - { - // Nothing to do here. - return; - } - else if (task.Status == TaskStatus.Faulted) - { - HandleException(task.Exception); - return; - } - } - - // The Task is incomplete. - // Queue up the task and we can inspect it later. - batch = batch ?? new List(); - batch.Add(GetErrorHandledTask(task)); - } - - private void RenderInExistingBatch(RenderQueueEntry renderQueueEntry) - { - var componentState = renderQueueEntry.ComponentState; - Log.RenderingComponent(_logger, componentState); - componentState.RenderIntoBatch(_batchBuilder, renderQueueEntry.RenderFragment); - - List exceptions = null; - - // Process disposal queue now in case it causes further component renders to be enqueued - while (_batchBuilder.ComponentDisposalQueue.Count > 0) - { - var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue(); - var disposeComponentState = GetRequiredComponentState(disposeComponentId); - Log.DisposingComponent(_logger, disposeComponentState); - if (!disposeComponentState.TryDisposeInBatch(_batchBuilder, out var exception)) - { - exceptions ??= new List(); - exceptions.Add(exception); - } - _componentStateById.Remove(disposeComponentId); - _batchBuilder.DisposedComponentIds.Append(disposeComponentId); - } - - if (exceptions?.Count > 1) - { - HandleException(new AggregateException("Exceptions were encountered while disposing components.", exceptions)); - } - else if (exceptions?.Count == 1) - { - HandleException(exceptions[0]); - } - } - - private void RemoveEventHandlerIds(ArrayRange eventHandlerIds, Task afterTaskIgnoreErrors) - { - if (eventHandlerIds.Count == 0) - { - return; - } - - if (afterTaskIgnoreErrors.IsCompleted) - { - var array = eventHandlerIds.Array; - var count = eventHandlerIds.Count; - for (var i = 0; i < count; i++) - { - var eventHandlerIdToRemove = array[i]; - _eventBindings.Remove(eventHandlerIdToRemove); - _eventHandlerIdReplacements.Remove(eventHandlerIdToRemove); - } - } - else - { - _ = ContinueAfterTask(eventHandlerIds, afterTaskIgnoreErrors); - } - - // Factor out the async part into a separate local method purely so, in the - // synchronous case, there's no state machine or task construction - async Task ContinueAfterTask(ArrayRange eventHandlerIds, Task afterTaskIgnoreErrors) - { - // We need to delay the actual removal (e.g., until we've confirmed the client - // has processed the batch and hence can be sure not to reuse the handler IDs - // any further). We must clone the data because the underlying RenderBatchBuilder - // may be reused and hence modified by an unrelated subsequent batch. - var eventHandlerIdsClone = eventHandlerIds.Clone(); - - try - { - await afterTaskIgnoreErrors; - } - catch (Exception) - { - // As per method contract, we're not error-handling the task. - // That remains the caller's business. - } - - // We know the next execution will complete synchronously, so no infinite loop - RemoveEventHandlerIds(eventHandlerIdsClone, Task.CompletedTask); - } - } - - private async Task GetErrorHandledTask(Task taskToHandle) - { - try - { - await taskToHandle; - } - catch (Exception ex) - { - if (!taskToHandle.IsCanceled) - { - // Ignore errors due to task cancellations. - HandleException(ex); - } - } - } - - private void UpdateRenderTreeToMatchClientState(ulong eventHandlerId, EventFieldInfo fieldInfo) - { - var componentState = GetOptionalComponentState(fieldInfo.ComponentId); - if (componentState != null) - { - RenderTreeUpdater.UpdateToMatchClientState( - componentState.CurrentRenderTree, - eventHandlerId, - fieldInfo.FieldValue); - } - } - - /// - /// Releases all resources currently used by this instance. - /// - /// if this method is being invoked by , otherwise . - protected virtual void Dispose(bool disposing) - { - _disposed = true; - - // It's important that we handle all exceptions here before reporting any of them. - // This way we can dispose all components before an error handler kicks in. - List exceptions = null; - foreach (var componentState in _componentStateById.Values) - { - Log.DisposingComponent(_logger, componentState); - - if (componentState.Component is IDisposable disposable) - { - try - { - componentState.Dispose(); - } - catch (Exception exception) - { - exceptions ??= new List(); - exceptions.Add(exception); - } - } - } - - _componentStateById.Clear(); // So we know they were all disposed - _batchBuilder.Dispose(); - - if (exceptions?.Count > 1) - { - HandleException(new AggregateException("Exceptions were encountered while disposing components.", exceptions)); - } - else if (exceptions?.Count == 1) - { - HandleException(exceptions[0]); - } - } - - /// - /// Releases all resources currently used by this instance. - /// - public void Dispose() - { - Dispose(disposing: true); - } - } -} diff --git a/src/Components/Components/src/RenderTree/StackObjectPool.cs b/src/Components/Components/src/RenderTree/StackObjectPool.cs deleted file mode 100644 index a2c9c1f5241b..000000000000 --- a/src/Components/Components/src/RenderTree/StackObjectPool.cs +++ /dev/null @@ -1,75 +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; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - // This is a very simple object pool that requires Get and Return calls to be - // balanced as in a stack. It retains up to 'maxPreservedItems' instances in - // memory, then for any further requests it supplies untracked instances. - - internal class StackObjectPool where T : class - { - private readonly int _maxPreservedItems; - private readonly Func _instanceFactory; - private readonly T[] _contents; - private int _numSuppliedItems; - private int _numTrackedItems; - - public StackObjectPool(int maxPreservedItems, Func instanceFactory) - { - _maxPreservedItems = maxPreservedItems; - _instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory)); - _contents = new T[_maxPreservedItems]; - } - - public T Get() - { - _numSuppliedItems++; - - if (_numSuppliedItems <= _maxPreservedItems) - { - if (_numTrackedItems < _numSuppliedItems) - { - // Need to allocate a new one - var newItem = _instanceFactory(); - _contents[_numTrackedItems++] = newItem; - return newItem; - } - else - { - // Can use one that's already in the pool - return _contents[_numSuppliedItems - 1]; - } - } - else - { - // Pool is full; return untracked instance - return _instanceFactory(); - } - } - - public void Return(T instance) - { - if (_numSuppliedItems <= 0) - { - throw new InvalidOperationException("There are no outstanding instances to return."); - } - else if (_numSuppliedItems <= _maxPreservedItems) - { - // We check you're returning the right instance only as a way of - // catching Get/Return mismatch bugs - var expectedInstance = _contents[_numSuppliedItems - 1]; - if (!ReferenceEquals(instance, expectedInstance)) - { - throw new ArgumentException($"Attempting to return wrong pooled instance. {nameof(Get)}/{nameof(Return)} calls must form a stack."); - } - } - - // It's a valid call. Track that we're no longer "supplying" the top item, - // but keep the instance in the _contents array for future reuse. - _numSuppliedItems--; - } - } -} diff --git a/src/Components/Components/src/Rendering/ComponentState.cs b/src/Components/Components/src/Rendering/ComponentState.cs deleted file mode 100644 index dc372424b9ad..000000000000 --- a/src/Components/Components/src/Rendering/ComponentState.cs +++ /dev/null @@ -1,218 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - /// - /// Tracks the rendering state associated with an instance - /// within the context of a . This is an internal implementation - /// detail of . - /// - internal class ComponentState : IDisposable - { - private readonly Renderer _renderer; - private readonly IReadOnlyList _cascadingParameters; - private readonly bool _hasAnyCascadingParameterSubscriptions; - private RenderTreeBuilder _renderTreeBuilderPrevious; - private ArrayBuilder _latestDirectParametersSnapshot; // Lazily instantiated - private bool _componentWasDisposed; - - /// - /// Constructs an instance of . - /// - /// The with which the new instance should be associated. - /// The externally visible identifier for the . The identifier must be unique in the context of the . - /// The whose state is being tracked. - /// The for the parent component, or null if this is a root component. - public ComponentState(Renderer renderer, int componentId, IComponent component, ComponentState parentComponentState) - { - ComponentId = componentId; - ParentComponentState = parentComponentState; - Component = component ?? throw new ArgumentNullException(nameof(component)); - _renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); - _cascadingParameters = CascadingParameterState.FindCascadingParameters(this); - CurrentRenderTree = new RenderTreeBuilder(); - _renderTreeBuilderPrevious = new RenderTreeBuilder(); - - if (_cascadingParameters != null) - { - _hasAnyCascadingParameterSubscriptions = AddCascadingParameterSubscriptions(); - } - } - - // TODO: Change the type to 'long' when the Mono runtime has more complete support for passing longs in .NET->JS calls - public int ComponentId { get; } - public IComponent Component { get; } - public ComponentState ParentComponentState { get; } - public RenderTreeBuilder CurrentRenderTree { get; private set; } - - public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment) - { - // A component might be in the render queue already before getting disposed by an - // earlier entry in the render queue. In that case, rendering is a no-op. - if (_componentWasDisposed) - { - return; - } - - // Swap the old and new tree builders - (CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree); - - CurrentRenderTree.Clear(); - renderFragment(CurrentRenderTree); - - var diff = RenderTreeDiffBuilder.ComputeDiff( - _renderer, - batchBuilder, - ComponentId, - _renderTreeBuilderPrevious.GetFrames(), - CurrentRenderTree.GetFrames()); - batchBuilder.UpdatedComponentDiffs.Append(diff); - batchBuilder.InvalidateParameterViews(); - } - - public bool TryDisposeInBatch(RenderBatchBuilder batchBuilder, out Exception exception) - { - _componentWasDisposed = true; - exception = null; - - try - { - if (Component is IDisposable disposable) - { - disposable.Dispose(); - } - } - catch (Exception ex) - { - exception = ex; - } - - // We don't expect these things to throw. - RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrentRenderTree.GetFrames()); - - if (_hasAnyCascadingParameterSubscriptions) - { - RemoveCascadingParameterSubscriptions(); - } - - DisposeBuffers(); - - return exception == null; - } - - // Callers expect this method to always return a faulted task. - public Task NotifyRenderCompletedAsync() - { - if (Component is IHandleAfterRender handlerAfterRender) - { - try - { - return handlerAfterRender.OnAfterRenderAsync(); - } - catch (OperationCanceledException cex) - { - return Task.FromCanceled(cex.CancellationToken); - } - catch (Exception ex) - { - return Task.FromException(ex); - } - } - - return Task.CompletedTask; - } - - public void SetDirectParameters(ParameterView parameters) - { - // Note: We should be careful to ensure that the framework never calls - // IComponent.SetParametersAsync directly elsewhere. We should only call it - // via ComponentState.SetDirectParameters (or NotifyCascadingValueChanged below). - // If we bypass this, the component won't receive the cascading parameters nor - // will it update its snapshot of direct parameters. - - if (_hasAnyCascadingParameterSubscriptions) - { - // We may need to replay these direct parameters later (in NotifyCascadingValueChanged), - // but we can't guarantee that the original underlying data won't have mutated in the - // meantime, since it's just an index into the parent's RenderTreeFrames buffer. - if (_latestDirectParametersSnapshot == null) - { - _latestDirectParametersSnapshot = new ArrayBuilder(); - } - - parameters.CaptureSnapshot(_latestDirectParametersSnapshot); - } - - if (_cascadingParameters != null) - { - parameters = parameters.WithCascadingParameters(_cascadingParameters); - } - - _renderer.AddToPendingTasks(Component.SetParametersAsync(parameters)); - } - - public void NotifyCascadingValueChanged(in ParameterViewLifetime lifetime) - { - var directParams = _latestDirectParametersSnapshot != null - ? new ParameterView(lifetime, _latestDirectParametersSnapshot.Buffer, 0) - : ParameterView.Empty; - var allParams = directParams.WithCascadingParameters(_cascadingParameters); - var task = Component.SetParametersAsync(allParams); - _renderer.AddToPendingTasks(task); - } - - private bool AddCascadingParameterSubscriptions() - { - var hasSubscription = false; - var numCascadingParameters = _cascadingParameters.Count; - - for (var i = 0; i < numCascadingParameters; i++) - { - var valueSupplier = _cascadingParameters[i].ValueSupplier; - if (!valueSupplier.CurrentValueIsFixed) - { - valueSupplier.Subscribe(this); - hasSubscription = true; - } - } - - return hasSubscription; - } - - private void RemoveCascadingParameterSubscriptions() - { - var numCascadingParameters = _cascadingParameters.Count; - for (var i = 0; i < numCascadingParameters; i++) - { - var supplier = _cascadingParameters[i].ValueSupplier; - if (!supplier.CurrentValueIsFixed) - { - supplier.Unsubscribe(this); - } - } - } - - public void Dispose() - { - DisposeBuffers(); - - if (Component is IDisposable disposable) - { - disposable.Dispose(); - } - } - - private void DisposeBuffers() - { - ((IDisposable)_renderTreeBuilderPrevious).Dispose(); - ((IDisposable)CurrentRenderTree).Dispose(); - _latestDirectParametersSnapshot?.Dispose(); - } - } -} diff --git a/src/Components/Components/src/Rendering/KeyedItemInfo.cs b/src/Components/Components/src/Rendering/KeyedItemInfo.cs deleted file mode 100644 index c8a7de5e1aef..000000000000 --- a/src/Components/Components/src/Rendering/KeyedItemInfo.cs +++ /dev/null @@ -1,35 +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.Rendering -{ - // Used internally during diffing to track what we know about keyed items and their positions - internal readonly struct KeyedItemInfo - { - public readonly int OldIndex; - public readonly int NewIndex; - public readonly int OldSiblingIndex; - public readonly int NewSiblingIndex; - - public KeyedItemInfo(int oldIndex, int newIndex) - { - OldIndex = oldIndex; - NewIndex = newIndex; - OldSiblingIndex = -1; - NewSiblingIndex = -1; - } - - private KeyedItemInfo(in KeyedItemInfo copyFrom, int oldSiblingIndex, int newSiblingIndex) - { - this = copyFrom; - OldSiblingIndex = oldSiblingIndex; - NewSiblingIndex = newSiblingIndex; - } - - public KeyedItemInfo WithOldSiblingIndex(int oldSiblingIndex) - => new KeyedItemInfo(this, oldSiblingIndex, NewSiblingIndex); - - public KeyedItemInfo WithNewSiblingIndex(int newSiblingIndex) - => new KeyedItemInfo(this, OldSiblingIndex, newSiblingIndex); - } -} diff --git a/src/Components/Components/src/Rendering/ParameterViewLifetime.cs b/src/Components/Components/src/Rendering/ParameterViewLifetime.cs deleted file mode 100644 index aefcb89180c9..000000000000 --- a/src/Components/Components/src/Rendering/ParameterViewLifetime.cs +++ /dev/null @@ -1,31 +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; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - internal readonly struct ParameterViewLifetime - { - private readonly RenderBatchBuilder _owner; - private readonly int _stamp; - - public static readonly ParameterViewLifetime Unbound = default; - - public ParameterViewLifetime(RenderBatchBuilder owner) - { - _owner = owner; - _stamp = owner.ParameterViewValidityStamp; - } - - public void AssertNotExpired() - { - // If _owner is null, this instance is default(ParameterViewLifetime), which is - // the same as ParameterViewLifetime.Unbound. That means it never expires. - if (_owner != null && _owner.ParameterViewValidityStamp != _stamp) - { - throw new InvalidOperationException($"The {nameof(ParameterView)} instance can no longer be read because it has expired. {nameof(ParameterView)} can only be read synchronously and must not be stored for later use."); - } - } - } -} diff --git a/src/Components/Components/src/Rendering/RenderBatchBuilder.cs b/src/Components/Components/src/Rendering/RenderBatchBuilder.cs deleted file mode 100644 index d4223bbce280..000000000000 --- a/src/Components/Components/src/Rendering/RenderBatchBuilder.cs +++ /dev/null @@ -1,93 +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 Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - /// - /// Collects the data produced by the rendering system during the course - /// of rendering a single batch. This tracks both the final output data - /// and the intermediate states (such as the queue of components still to - /// be rendered). - /// - internal class RenderBatchBuilder : IDisposable - { - // A value that, if changed, causes expiry of all ParameterView instances issued - // for this RenderBatchBuilder. This is to prevent invalid reads from arrays that - // may have been returned to the shared pool. - private int _parameterViewValidityStamp; - - // Primary result data - public ArrayBuilder UpdatedComponentDiffs { get; } = new ArrayBuilder(); - public ArrayBuilder DisposedComponentIds { get; } = new ArrayBuilder(); - public ArrayBuilder DisposedEventHandlerIds { get; } = new ArrayBuilder(); - - // Buffers referenced by UpdatedComponentDiffs - public ArrayBuilder EditsBuffer { get; } = new ArrayBuilder(64); - public ArrayBuilder ReferenceFramesBuffer { get; } = new ArrayBuilder(64); - - // State of render pipeline - public Queue ComponentRenderQueue { get; } = new Queue(); - public Queue ComponentDisposalQueue { get; } = new Queue(); - - // Scratch data structure for understanding attribute diffs. - public Dictionary AttributeDiffSet { get; } = new Dictionary(); - - public int ParameterViewValidityStamp => _parameterViewValidityStamp; - - internal StackObjectPool> KeyedItemInfoDictionaryPool { get; } - = new StackObjectPool>(maxPreservedItems: 10, () => new Dictionary()); - - public void ClearStateForCurrentBatch() - { - // This method is used to reset the builder back to a default state so it can - // begin building the next batch. That means clearing all the tracked state, but - // *not* clearing ComponentRenderQueue because that may hold information about - // the next batch we want to build. We shouldn't ever need to clear - // ComponentRenderQueue explicitly, because it gets cleared as an aspect of - // processing the render queue. - - EditsBuffer.Clear(); - ReferenceFramesBuffer.Clear(); - UpdatedComponentDiffs.Clear(); - DisposedComponentIds.Clear(); - DisposedEventHandlerIds.Clear(); - AttributeDiffSet.Clear(); - } - - public RenderBatch ToBatch() - => new RenderBatch( - UpdatedComponentDiffs.ToRange(), - ReferenceFramesBuffer.ToRange(), - DisposedComponentIds.ToRange(), - DisposedEventHandlerIds.ToRange()); - - public void InvalidateParameterViews() - { - // Wrapping is fine because all that matters is whether a snapshotted value matches - // the current one. There's no plausible case where it wraps around and happens to - // increment all the way back to a previously-snapshotted value on the exact same - // call that's checking the value. - if (_parameterViewValidityStamp == int.MaxValue) - { - _parameterViewValidityStamp = int.MinValue; - } - else - { - _parameterViewValidityStamp++; - } - } - - public void Dispose() - { - EditsBuffer.Dispose(); - ReferenceFramesBuffer.Dispose(); - UpdatedComponentDiffs.Dispose(); - DisposedComponentIds.Dispose(); - DisposedEventHandlerIds.Dispose(); - } - } -} diff --git a/src/Components/Components/src/Rendering/RenderQueueEntry.cs b/src/Components/Components/src/Rendering/RenderQueueEntry.cs deleted file mode 100644 index 09e5e9c3272a..000000000000 --- a/src/Components/Components/src/Rendering/RenderQueueEntry.cs +++ /dev/null @@ -1,19 +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; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - internal readonly struct RenderQueueEntry - { - public readonly ComponentState ComponentState; - public readonly RenderFragment RenderFragment; - - public RenderQueueEntry(ComponentState componentState, RenderFragment renderFragment) - { - ComponentState = componentState; - RenderFragment = renderFragment ?? throw new ArgumentNullException(nameof(renderFragment)); - } - } -} diff --git a/src/Components/Components/src/Rendering/RenderTreeBuilder.cs b/src/Components/Components/src/Rendering/RenderTreeBuilder.cs deleted file mode 100644 index f8a28273e4d3..000000000000 --- a/src/Components/Components/src/Rendering/RenderTreeBuilder.cs +++ /dev/null @@ -1,773 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - // IMPORTANT - // - // Many of these names are used in code generation. Keep these in sync with the code generation code - // See: aspnet/AspNetCore-Tooling - - /// - /// Provides methods for building a collection of entries. - /// - public sealed class RenderTreeBuilder : IDisposable - { - private readonly static object BoxedTrue = true; - private readonly static object BoxedFalse = false; - private readonly static string ComponentReferenceCaptureInvalidParentMessage = $"Component reference captures may only be added as children of frames of type {RenderTreeFrameType.Component}"; - - private readonly ArrayBuilder _entries = new ArrayBuilder(); - private readonly Stack _openElementIndices = new Stack(); - private RenderTreeFrameType? _lastNonAttributeFrameType; - private bool _hasSeenAddMultipleAttributes; - private Dictionary _seenAttributeNames; - - /// - /// The reserved parameter name used for supplying child content. - /// - private const string ChildContent = nameof(ChildContent); - - /// - /// Appends a frame representing an element, i.e., a container for other frames. - /// In order for the state to be valid, you must - /// also call immediately after appending the - /// new element's child frames. - /// - /// An integer that represents the position of the instruction in the source code. - /// A value representing the type of the element. - public void OpenElement(int sequence, string elementName) - { - // We are entering a new scope, since we track the "duplicate attributes" per - // element/component we might need to clean them up now. - if (_hasSeenAddMultipleAttributes) - { - var indexOfLastElementOrComponent = _openElementIndices.Peek(); - ProcessDuplicateAttributes(first: indexOfLastElementOrComponent + 1); - } - - _openElementIndices.Push(_entries.Count); - Append(RenderTreeFrame.Element(sequence, elementName)); - } - - /// - /// Marks a previously appended element frame as closed. Calls to this method - /// must be balanced with calls to . - /// - public void CloseElement() - { - var indexOfEntryBeingClosed = _openElementIndices.Pop(); - - // We might be closing an element with only attributes, run the duplicate cleanup pass - // if necessary. - if (_hasSeenAddMultipleAttributes) - { - ProcessDuplicateAttributes(first: indexOfEntryBeingClosed + 1); - } - - ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; - entry = entry.WithElementSubtreeLength(_entries.Count - indexOfEntryBeingClosed); - } - - /// - /// Appends a frame representing markup content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content for the new markup frame. - public void AddMarkupContent(int sequence, string markupContent) - => Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty)); - - /// - /// Appends a frame representing text content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content for the new text frame. - public void AddContent(int sequence, string textContent) - => Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty)); - - /// - /// Appends frames representing an arbitrary fragment of content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content to append. - public void AddContent(int sequence, RenderFragment fragment) - { - if (fragment != null) - { - // We surround the fragment with a region delimiter to indicate that the - // sequence numbers inside the fragment are unrelated to the sequence numbers - // outside it. If we didn't do this, the diffing logic might produce inefficient - // diffs depending on how the sequence numbers compared. - OpenRegion(sequence); - fragment(this); - CloseRegion(); - } - } - - /// - /// Appends frames representing an arbitrary fragment of content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content to append. - /// The value used by . - public void AddContent(int sequence, RenderFragment fragment, TValue value) - { - if (fragment != null) - { - AddContent(sequence, fragment(value)); - } - } - - /// - /// Appends a frame representing markup content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content for the new markup frame. - public void AddContent(int sequence, MarkupString markupContent) - => AddMarkupContent(sequence, markupContent.Value); - - /// - /// Appends a frame representing text content. - /// - /// An integer that represents the position of the instruction in the source code. - /// Content for the new text frame. - public void AddContent(int sequence, object textContent) - => AddContent(sequence, textContent?.ToString()); - - /// - /// - /// Appends a frame representing a bool-valued attribute. - /// - /// - /// The attribute is associated with the most recently added element. If the value is false and the - /// current element is not a component, the frame will be omitted. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - public void AddAttribute(int sequence, string name, bool value) - { - AssertCanAddAttribute(); - if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - Append(RenderTreeFrame.Attribute(sequence, name, value ? BoxedTrue : BoxedFalse)); - } - else if (value) - { - // Don't add 'false' attributes for elements. We want booleans to map to the presence - // or absence of an attribute, and false => "False" which isn't falsy in js. - Append(RenderTreeFrame.Attribute(sequence, name, BoxedTrue)); - } - else - { - TrackAttributeName(name); - } - } - - /// - /// - /// Appends a frame representing a string-valued attribute. - /// - /// - /// The attribute is associated with the most recently added element. If the value is null and the - /// current element is not a component, the frame will be omitted. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - public void AddAttribute(int sequence, string name, string value) - { - AssertCanAddAttribute(); - if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - Append(RenderTreeFrame.Attribute(sequence, name, value)); - } - else - { - TrackAttributeName(name); - } - } - - /// - /// - /// Appends a frame representing a delegate-valued attribute. - /// - /// - /// The attribute is associated with the most recently added element. If the value is null and the - /// current element is not a component, the frame will be omitted. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - public void AddAttribute(int sequence, string name, MulticastDelegate value) - { - AssertCanAddAttribute(); - if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - Append(RenderTreeFrame.Attribute(sequence, name, value)); - } - else - { - TrackAttributeName(name); - } - } - - /// - /// - /// Appends a frame representing an attribute. - /// - /// - /// The attribute is associated with the most recently added element. If the value is null and the - /// current element is not a component, the frame will be omitted. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - /// - /// This method is provided for infrastructure purposes, and is used to support generated code - /// that uses . - /// - public void AddAttribute(int sequence, string name, EventCallback value) - { - AssertCanAddAttribute(); - if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - // Since this is a component, we need to preserve the type of the EventCallabck, so we have - // to box. - Append(RenderTreeFrame.Attribute(sequence, name, (object)value)); - } - else if (value.RequiresExplicitReceiver) - { - // If we need to preserve the receiver, we just box the EventCallback - // so we can get it out on the other side. - Append(RenderTreeFrame.Attribute(sequence, name, (object)value)); - } - else if (value.HasDelegate) - { - // In the common case the receiver is also the delegate's target, so we - // just need to retain the delegate. This allows us to avoid an allocation. - Append(RenderTreeFrame.Attribute(sequence, name, value.Delegate)); - } - else - { - // Track the attribute name if needed since we elided the frame. - TrackAttributeName(name); - } - } - - /// - /// - /// Appends a frame representing an attribute. - /// - /// - /// The attribute is associated with the most recently added element. If the value is null and the - /// current element is not a component, the frame will be omitted. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - /// - /// This method is provided for infrastructure purposes, and is used to support generated code - /// that uses . - /// - public void AddAttribute(int sequence, string name, EventCallback value) - { - AssertCanAddAttribute(); - if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - // Since this is a component, we need to preserve the type of the EventCallback, so we have - // to box. - Append(RenderTreeFrame.Attribute(sequence, name, (object)value)); - } - else if (value.RequiresExplicitReceiver) - { - // If we need to preserve the receiver - we convert this to an untyped EventCallback. We don't - // need to preserve the type of an EventCallback when it's invoked from the DOM. - Append(RenderTreeFrame.Attribute(sequence, name, (object)value.AsUntyped())); - } - else if (value.HasDelegate) - { - // In the common case the receiver is also the delegate's target, so we - // just need to retain the delegate. This allows us to avoid an allocation. - Append(RenderTreeFrame.Attribute(sequence, name, value.Delegate)); - } - else - { - // Track the attribute name if needed since we elided the frame. - TrackAttributeName(name); - } - } - - /// - /// Appends a frame representing a string-valued attribute. - /// The attribute is associated with the most recently added element. If the value is null, or - /// the value false and the current element is not a component, the - /// frame will be omitted. - /// - /// An integer that represents the position of the instruction in the source code. - /// The name of the attribute. - /// The value of the attribute. - public void AddAttribute(int sequence, string name, object value) - { - // This looks a bit daunting because we need to handle the boxed/object version of all of the - // types that AddAttribute special cases. - if (_lastNonAttributeFrameType == RenderTreeFrameType.Element) - { - if (value == null) - { - // Treat 'null' attribute values for elements as a conditional attribute. - TrackAttributeName(name); - } - else if (value is bool boolValue) - { - if (boolValue) - { - Append(RenderTreeFrame.Attribute(sequence, name, BoxedTrue)); - } - else - { - // Don't add anything for false bool value. - TrackAttributeName(name); - } - } - else if (value is IEventCallback callbackValue) - { - if (callbackValue.HasDelegate) - { - Append(RenderTreeFrame.Attribute(sequence, name, callbackValue.UnpackForRenderTree())); - } - else - { - TrackAttributeName(name); - } - } - else if (value is MulticastDelegate) - { - Append(RenderTreeFrame.Attribute(sequence, name, value)); - } - else - { - // The value is either a string, or should be treated as a string. - Append(RenderTreeFrame.Attribute(sequence, name, value.ToString())); - } - } - else if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) - { - // If this is a component, we always want to preserve the original type. - Append(RenderTreeFrame.Attribute(sequence, name, value)); - } - else - { - // This is going to throw. Calling it just to get a consistent exception message. - AssertCanAddAttribute(); - } - } - - /// - /// - /// Appends a frame representing an attribute. - /// - /// - /// The attribute is associated with the most recently added element. - /// - /// - /// An integer that represents the position of the instruction in the source code. - /// A holding the name and value of the attribute. - public void AddAttribute(int sequence, in RenderTreeFrame frame) - { - if (frame.FrameType != RenderTreeFrameType.Attribute) - { - throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}."); - } - - AssertCanAddAttribute(); - Append(frame.WithAttributeSequence(sequence)); - } - - /// - /// Adds frames representing multiple attributes with the same sequence number. - /// - /// An integer that represents the position of the instruction in the source code. - /// A collection of key-value pairs representing attributes. - public void AddMultipleAttributes(int sequence, IEnumerable> attributes) - { - // Calling this up-front just to make sure we validate before mutating anything. - AssertCanAddAttribute(); - - if (attributes != null) - { - _hasSeenAddMultipleAttributes = true; - - foreach (var attribute in attributes) - { - // This will call the AddAttribute(int, string, object) overload. - // - // This is fine because we try to make the object overload behave identically - // to the others. - AddAttribute(sequence, attribute.Key, attribute.Value); - } - } - } - - /// - /// - /// Indicates that the preceding attribute represents an event handler - /// whose execution updates the attribute with name . - /// - /// - /// This information is used by the rendering system to determine whether - /// to accept a value update for the other attribute when receiving a - /// call to the event handler. - /// - /// - /// The name of another attribute whose value can be updated when the event handler is executed. - public void SetUpdatesAttributeName(string updatesAttributeName) - { - if (_entries.Count == 0) - { - throw new InvalidOperationException("No preceding attribute frame exists."); - } - - ref var prevFrame = ref _entries.Buffer[_entries.Count - 1]; - if (prevFrame.FrameType != RenderTreeFrameType.Attribute) - { - throw new InvalidOperationException($"Incorrect frame type: '{prevFrame.FrameType}'"); - } - - prevFrame = prevFrame.WithAttributeEventUpdatesAttributeName(updatesAttributeName); - } - - /// - /// Appends a frame representing a child component. - /// - /// The type of the child component. - /// An integer that represents the position of the instruction in the source code. - public void OpenComponent(int sequence) where TComponent : IComponent - => OpenComponentUnchecked(sequence, typeof(TComponent)); - - /// - /// Appends a frame representing a child component. - /// - /// An integer that represents the position of the instruction in the source code. - /// The type of the child component. - public void OpenComponent(int sequence, Type componentType) - { - if (!typeof(IComponent).IsAssignableFrom(componentType)) - { - throw new ArgumentException($"The component type must implement {typeof(IComponent).FullName}."); - } - - OpenComponentUnchecked(sequence, componentType); - } - - /// - /// Assigns the specified key value to the current element or component. - /// - /// The value for the key. - public void SetKey(object value) - { - if (value == null) - { - // Null is equivalent to not having set a key, which is valuable because Razor syntax doesn't have an - // easy way to have conditional directive attributes - return; - } - - var parentFrameIndex = GetCurrentParentFrameIndex(); - if (!parentFrameIndex.HasValue) - { - throw new InvalidOperationException("Cannot set a key outside the scope of a component or element."); - } - - var parentFrameIndexValue = parentFrameIndex.Value; - ref var parentFrame = ref _entries.Buffer[parentFrameIndexValue]; - switch (parentFrame.FrameType) - { - case RenderTreeFrameType.Element: - parentFrame = parentFrame.WithElementKey(value); // It's a ref var, so this writes to the array - break; - case RenderTreeFrameType.Component: - parentFrame = parentFrame.WithComponentKey(value); // It's a ref var, so this writes to the array - break; - default: - throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}."); - } - } - - private void OpenComponentUnchecked(int sequence, Type componentType) - { - // We are entering a new scope, since we track the "duplicate attributes" per - // element/component we might need to clean them up now. - if (_hasSeenAddMultipleAttributes) - { - var indexOfLastElementOrComponent = _openElementIndices.Peek(); - ProcessDuplicateAttributes(first: indexOfLastElementOrComponent + 1); - } - - _openElementIndices.Push(_entries.Count); - Append(RenderTreeFrame.ChildComponent(sequence, componentType)); - } - - /// - /// Marks a previously appended component frame as closed. Calls to this method - /// must be balanced with calls to . - /// - public void CloseComponent() - { - var indexOfEntryBeingClosed = _openElementIndices.Pop(); - - // We might be closing a component with only attributes. Run the attribute cleanup pass - // if necessary. - if (_hasSeenAddMultipleAttributes) - { - ProcessDuplicateAttributes(first: indexOfEntryBeingClosed + 1); - } - - ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; - entry = entry.WithComponentSubtreeLength(_entries.Count - indexOfEntryBeingClosed); - } - - /// - /// Appends a frame representing an instruction to capture a reference to the parent element. - /// - /// An integer that represents the position of the instruction in the source code. - /// An action to be invoked whenever the reference value changes. - public void AddElementReferenceCapture(int sequence, Action elementReferenceCaptureAction) - { - if (GetCurrentParentFrameType() != RenderTreeFrameType.Element) - { - throw new InvalidOperationException($"Element reference captures may only be added as children of frames of type {RenderTreeFrameType.Element}"); - } - - Append(RenderTreeFrame.ElementReferenceCapture(sequence, elementReferenceCaptureAction)); - } - - /// - /// Appends a frame representing an instruction to capture a reference to the parent component. - /// - /// An integer that represents the position of the instruction in the source code. - /// An action to be invoked whenever the reference value changes. - public void AddComponentReferenceCapture(int sequence, Action componentReferenceCaptureAction) - { - var parentFrameIndex = GetCurrentParentFrameIndex(); - if (!parentFrameIndex.HasValue) - { - throw new InvalidOperationException(ComponentReferenceCaptureInvalidParentMessage); - } - - var parentFrameIndexValue = parentFrameIndex.Value; - if (_entries.Buffer[parentFrameIndexValue].FrameType != RenderTreeFrameType.Component) - { - throw new InvalidOperationException(ComponentReferenceCaptureInvalidParentMessage); - } - - Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue)); - } - - /// - /// Appends a frame representing a region of frames. - /// - /// An integer that represents the position of the instruction in the source code. - public void OpenRegion(int sequence) - { - // We are entering a new scope, since we track the "duplicate attributes" per - // element/component we might need to clean them up now. - if (_hasSeenAddMultipleAttributes) - { - var indexOfLastElementOrComponent = _openElementIndices.Peek(); - ProcessDuplicateAttributes(first: indexOfLastElementOrComponent + 1); - } - - _openElementIndices.Push(_entries.Count); - Append(RenderTreeFrame.Region(sequence)); - } - - /// - /// Marks a previously appended region frame as closed. Calls to this method - /// must be balanced with calls to . - /// - public void CloseRegion() - { - var indexOfEntryBeingClosed = _openElementIndices.Pop(); - ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; - entry = entry.WithRegionSubtreeLength(_entries.Count - indexOfEntryBeingClosed); - } - - private void AssertCanAddAttribute() - { - if (_lastNonAttributeFrameType != RenderTreeFrameType.Element - && _lastNonAttributeFrameType != RenderTreeFrameType.Component) - { - throw new InvalidOperationException($"Attributes may only be added immediately after frames of type {RenderTreeFrameType.Element} or {RenderTreeFrameType.Component}"); - } - } - - private int? GetCurrentParentFrameIndex() - => _openElementIndices.Count == 0 ? (int?)null : _openElementIndices.Peek(); - - private RenderTreeFrameType? GetCurrentParentFrameType() - { - var parentIndex = GetCurrentParentFrameIndex(); - return parentIndex.HasValue - ? _entries.Buffer[parentIndex.Value].FrameType - : (RenderTreeFrameType?)null; - } - - /// - /// Clears the builder. - /// - public void Clear() - { - _entries.Clear(); - _openElementIndices.Clear(); - _lastNonAttributeFrameType = null; - _hasSeenAddMultipleAttributes = false; - _seenAttributeNames?.Clear(); - } - - // internal because this should only be used during the post-event tree patching logic - // It's expensive because it involves copying all the subsequent memory in the array - internal void InsertAttributeExpensive(int insertAtIndex, int sequence, string attributeName, object attributeValue) - { - // Replicate the same attribute omission logic as used elsewhere - if ((attributeValue == null) || (attributeValue is bool boolValue && !boolValue)) - { - return; - } - - _entries.InsertExpensive(insertAtIndex, RenderTreeFrame.Attribute(sequence, attributeName, attributeValue)); - } - - /// - /// Returns the values that have been appended. - /// - /// An array range of values. - public ArrayRange GetFrames() => - _entries.ToRange(); - - private void Append(in RenderTreeFrame frame) - { - var frameType = frame.FrameType; - _entries.Append(frame); - - if (frameType != RenderTreeFrameType.Attribute) - { - _lastNonAttributeFrameType = frame.FrameType; - } - } - - // Internal for testing - internal void ProcessDuplicateAttributes(int first) - { - Debug.Assert(_hasSeenAddMultipleAttributes); - - // When AddMultipleAttributes method has been called, we need to postprocess attributes while closing - // the element/component. However, we also don't know the end index we should look at because it - // will contain nested content. - var buffer = _entries.Buffer; - var last = _entries.Count - 1; - - for (var i = first; i <= last; i++) - { - if (buffer[i].FrameType != RenderTreeFrameType.Attribute) - { - last = i - 1; - break; - } - } - - // Now that we've found the last attribute, we can iterate backwards and process duplicates. - var seenAttributeNames = (_seenAttributeNames ??= new Dictionary(StringComparer.OrdinalIgnoreCase)); - for (var i = last; i >= first; i--) - { - ref var frame = ref buffer[i]; - Debug.Assert(frame.FrameType == RenderTreeFrameType.Attribute, $"Frame type is {frame.FrameType} at {i}"); - - if (!seenAttributeNames.TryGetValue(frame.AttributeName, out var index)) - { - // This is the first time seeing this attribute name. Add to the dictionary and move on. - seenAttributeNames.Add(frame.AttributeName, i); - } - else if (index < i) - { - // This attribute is overriding a "silent frame" where we didn't create a frame for an AddAttribute call. - // This is the case for a null event handler, or bool false value. - // - // We need to update our tracking, in case the attribute appeared 3 or more times. - seenAttributeNames[frame.AttributeName] = i; - } - else if (index > i) - { - // This attribute has been overridden. For now, blank out its name to *mark* it. We'll do a pass - // later to wipe it out. - frame = default; - } - else - { - // OK so index == i. How is that possible? Well it's possible for a "silent frame" immediately - // followed by setting the same attribute. Think of it this way, when we create a "silent frame" - // we have to track that attribute name with *some* index. - // - // The only index value we can safely use is _entries.Count (next available). This is fine because - // we never use these indexes to look stuff up, only for comparison. - // - // That gets you here, and there's no action to take. - } - } - - // This is the pass where we cleanup attributes that have been wiped out. - // - // We copy the entries we're keeping into the earlier parts of the list (preserving order). - // - // Note that we iterate to the end of the list here, there might be additional frames after the attributes - // (ref) or content) that need to move to the left. - var offset = first; - for (var i = first; i < _entries.Count; i++) - { - ref var frame = ref buffer[i]; - if (frame.FrameType != RenderTreeFrameType.None) - { - buffer[offset++] = frame; - } - } - - // Clean up now unused space at the end of the list. - var residue = _entries.Count - offset; - for (var i = 0; i < residue; i++) - { - _entries.RemoveLast(); - } - - seenAttributeNames.Clear(); - _hasSeenAddMultipleAttributes = false; - } - - // Internal for testing - internal void TrackAttributeName(string name) - { - if (!_hasSeenAddMultipleAttributes) - { - return; - } - - var seenAttributeNames = (_seenAttributeNames ??= new Dictionary(StringComparer.OrdinalIgnoreCase)); - seenAttributeNames[name] = _entries.Count; // See comment in ProcessAttributes for why this is OK. - } - - void IDisposable.Dispose() - { - _entries.Dispose(); - } - } -} diff --git a/src/Components/Components/src/Rendering/RenderTreeUpdater.cs b/src/Components/Components/src/Rendering/RenderTreeUpdater.cs deleted file mode 100644 index 139b3e09d752..000000000000 --- a/src/Components/Components/src/Rendering/RenderTreeUpdater.cs +++ /dev/null @@ -1,113 +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.RenderTree; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - internal class RenderTreeUpdater - { - public static void UpdateToMatchClientState(RenderTreeBuilder renderTreeBuilder, ulong eventHandlerId, object newFieldValue) - { - // We only allow the client to supply string or bool currently, since those are the only kinds of - // values we output on attributes that go to the client - if (!(newFieldValue is string || newFieldValue is bool)) - { - return; - } - - // Find the element that contains the event handler - var frames = renderTreeBuilder.GetFrames(); - var framesArray = frames.Array; - var framesLength = frames.Count; - var closestElementFrameIndex = -1; - for (var frameIndex = 0; frameIndex < framesLength; frameIndex++) - { - ref var frame = ref framesArray[frameIndex]; - switch (frame.FrameType) - { - case RenderTreeFrameType.Element: - closestElementFrameIndex = frameIndex; - break; - case RenderTreeFrameType.Attribute: - if (frame.AttributeEventHandlerId == eventHandlerId) - { - if (!string.IsNullOrEmpty(frame.AttributeEventUpdatesAttributeName)) - { - UpdateFrameToMatchClientState( - renderTreeBuilder, - framesArray, - closestElementFrameIndex, - frame.AttributeEventUpdatesAttributeName, - newFieldValue); - } - - // Whether or not we did update the frame, that was the one that matches - // the event handler ID, so no need to look any further - return; - } - break; - } - } - } - - private static void UpdateFrameToMatchClientState(RenderTreeBuilder renderTreeBuilder, RenderTreeFrame[] framesArray, int elementFrameIndex, string attributeName, object attributeValue) - { - // Find the attribute frame - ref var elementFrame = ref framesArray[elementFrameIndex]; - var elementSubtreeEndIndexExcl = elementFrameIndex + elementFrame.ElementSubtreeLength; - for (var attributeFrameIndex = elementFrameIndex + 1; attributeFrameIndex < elementSubtreeEndIndexExcl; attributeFrameIndex++) - { - ref var attributeFrame = ref framesArray[attributeFrameIndex]; - if (attributeFrame.FrameType != RenderTreeFrameType.Attribute) - { - // We're now looking at the descendants not attributes, so the search is over - break; - } - - if (attributeFrame.AttributeName == attributeName) - { - // Found an existing attribute we can update - attributeFrame = attributeFrame.WithAttributeValue(attributeValue); - return; - } - } - - // If we get here, we didn't find the desired attribute, so we have to insert a new frame for it - var insertAtIndex = elementFrameIndex + 1; - renderTreeBuilder.InsertAttributeExpensive(insertAtIndex, RenderTreeDiffBuilder.SystemAddedAttributeSequenceNumber, attributeName, attributeValue); - framesArray = renderTreeBuilder.GetFrames().Array; // Refresh in case it mutated due to the expansion - - // Update subtree length for this and all ancestor containers - // Ancestors can only be regions or other elements, since components can't "contain" elements inline - // We only have to walk backwards, since later entries in the frames array can't contain an earlier one - for (var otherFrameIndex = elementFrameIndex; otherFrameIndex >= 0; otherFrameIndex--) - { - ref var otherFrame = ref framesArray[otherFrameIndex]; - switch (otherFrame.FrameType) - { - case RenderTreeFrameType.Element: - { - var otherFrameSubtreeLength = otherFrame.ElementSubtreeLength; - var otherFrameEndIndexExcl = otherFrameIndex + otherFrameSubtreeLength; - if (otherFrameEndIndexExcl > elementFrameIndex) // i.e., contains the element we're inserting into - { - otherFrame = otherFrame.WithElementSubtreeLength(otherFrameSubtreeLength + 1); - } - break; - } - case RenderTreeFrameType.Region: - { - var otherFrameSubtreeLength = otherFrame.RegionSubtreeLength; - var otherFrameEndIndexExcl = otherFrameIndex + otherFrameSubtreeLength; - if (otherFrameEndIndexExcl > elementFrameIndex) // i.e., contains the element we're inserting into - { - otherFrame = otherFrame.WithRegionSubtreeLength(otherFrameSubtreeLength + 1); - } - break; - } - } - } - } - } -} diff --git a/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs b/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs deleted file mode 100644 index 176e4d83e456..000000000000 --- a/src/Components/Components/src/Rendering/RendererSynchronizationContext.cs +++ /dev/null @@ -1,312 +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.Diagnostics; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - [DebuggerDisplay("{_state,nq}")] - internal class RendererSynchronizationContext : SynchronizationContext - { - private static readonly ContextCallback ExecutionContextThunk = (object state) => - { - var item = (WorkItem)state; - item.SynchronizationContext.ExecuteSynchronously(null, item.Callback, item.State); - }; - - private static readonly Action BackgroundWorkThunk = (Task task, object state) => - { - var item = (WorkItem)state; - item.SynchronizationContext.ExecuteBackground(item); - }; - - private readonly State _state; - - public event UnhandledExceptionEventHandler UnhandledException; - - public RendererSynchronizationContext() - : this(new State()) - { - } - - private RendererSynchronizationContext(State state) - { - _state = state; - } - - public Task InvokeAsync(Action action) - { - var completion = new RendererSynchronizationTaskCompletionSource(action); - ExecuteSynchronouslyIfPossible((state) => - { - var completion = (RendererSynchronizationTaskCompletionSource)state; - try - { - completion.Callback(); - completion.SetResult(null); - } - catch (OperationCanceledException) - { - completion.SetCanceled(); - } - catch (Exception exception) - { - completion.SetException(exception); - } - }, completion); - - return completion.Task; - } - - public Task InvokeAsync(Func asyncAction) - { - var completion = new RendererSynchronizationTaskCompletionSource, object>(asyncAction); - ExecuteSynchronouslyIfPossible(async (state) => - { - var completion = (RendererSynchronizationTaskCompletionSource, object>)state; - try - { - await completion.Callback(); - completion.SetResult(null); - } - catch (OperationCanceledException) - { - completion.SetCanceled(); - } - catch (Exception exception) - { - completion.SetException(exception); - } - }, completion); - - return completion.Task; - } - - public Task InvokeAsync(Func function) - { - var completion = new RendererSynchronizationTaskCompletionSource, TResult>(function); - ExecuteSynchronouslyIfPossible((state) => - { - var completion = (RendererSynchronizationTaskCompletionSource, TResult>)state; - try - { - var result = completion.Callback(); - completion.SetResult(result); - } - catch (OperationCanceledException) - { - completion.SetCanceled(); - } - catch (Exception exception) - { - completion.SetException(exception); - } - }, completion); - - return completion.Task; - } - - public Task InvokeAsync(Func> asyncFunction) - { - var completion = new RendererSynchronizationTaskCompletionSource>, TResult>(asyncFunction); - ExecuteSynchronouslyIfPossible(async (state) => - { - var completion = (RendererSynchronizationTaskCompletionSource>, TResult>)state; - try - { - var result = await completion.Callback(); - completion.SetResult(result); - } - catch (OperationCanceledException) - { - completion.SetCanceled(); - } - catch (Exception exception) - { - completion.SetException(exception); - } - }, completion); - - return completion.Task; - } - - // asynchronously runs the callback - // - // NOTE: this must always run async. It's not legal here to execute the work item synchronously. - public override void Post(SendOrPostCallback d, object state) - { - lock (_state.Lock) - { - _state.Task = Enqueue(_state.Task, d, state, forceAsync: true); - } - } - - // synchronously runs the callback - public override void Send(SendOrPostCallback d, object state) - { - Task antecedant; - var completion = new TaskCompletionSource(); - - lock (_state.Lock) - { - antecedant = _state.Task; - _state.Task = completion.Task; - } - - // We have to block. That's the contract of Send - we don't expect this to be used - // in many scenarios in Components. - // - // Using Wait here is ok because the antecedant task will never throw. - antecedant.Wait(); - - ExecuteSynchronously(completion, d, state); - } - - // shallow copy - public override SynchronizationContext CreateCopy() - { - return new RendererSynchronizationContext(_state); - } - - // Similar to Post, but it can runs the work item synchronously if the context is not busy. - // - // This is the main code path used by components, we want to be able to run async work but only dispatch - // if necessary. - private void ExecuteSynchronouslyIfPossible(SendOrPostCallback d, object state) - { - TaskCompletionSource completion; - lock (_state.Lock) - { - if (!_state.Task.IsCompleted) - { - _state.Task = Enqueue(_state.Task, d, state); - return; - } - - // We can execute this synchronously because nothing is currently running - // or queued. - completion = new TaskCompletionSource(); - _state.Task = completion.Task; - } - - ExecuteSynchronously(completion, d, state); - } - - private Task Enqueue(Task antecedant, SendOrPostCallback d, object state, bool forceAsync = false) - { - // If we get here is means that a callback is being explicitly queued. Let's instead add it to the queue and yield. - // - // We use our own queue here to maintain the execution order of the callbacks scheduled here. Also - // we need a queue rather than just scheduling an item in the thread pool - those items would immediately - // block and hurt scalability. - // - // We need to capture the execution context so we can restore it later. This code is similar to - // the call path of ThreadPool.QueueUserWorkItem and System.Threading.QueueUserWorkItemCallback. - ExecutionContext executionContext = null; - if (!ExecutionContext.IsFlowSuppressed()) - { - executionContext = ExecutionContext.Capture(); - } - - var flags = forceAsync ? TaskContinuationOptions.RunContinuationsAsynchronously : TaskContinuationOptions.None; - return antecedant.ContinueWith(BackgroundWorkThunk, new WorkItem() - { - SynchronizationContext = this, - ExecutionContext = executionContext, - Callback = d, - State = state, - }, CancellationToken.None, flags, TaskScheduler.Current); - } - - private void ExecuteSynchronously( - TaskCompletionSource completion, - SendOrPostCallback d, - object state) - { - var original = Current; - try - { - SetSynchronizationContext(this); - _state.IsBusy = true; - - d(state); - } - finally - { - _state.IsBusy = false; - SetSynchronizationContext(original); - - completion?.SetResult(null); - } - } - - private void ExecuteBackground(WorkItem item) - { - if (item.ExecutionContext == null) - { - try - { - ExecuteSynchronously(null, item.Callback, item.State); - } - catch (Exception ex) - { - DispatchException(ex); - } - - return; - } - - // Perf - using a static thunk here to avoid a delegate allocation. - try - { - ExecutionContext.Run(item.ExecutionContext, ExecutionContextThunk, item); - } - catch (Exception ex) - { - DispatchException(ex); - } - } - - private void DispatchException(Exception ex) - { - var handler = UnhandledException; - if (handler != null) - { - handler(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); - } - } - - private class State - { - public bool IsBusy; // Just for debugging - public object Lock = new object(); - public Task Task = Task.CompletedTask; - - public override string ToString() - { - return $"{{ Busy: {IsBusy}, Pending Task: {Task} }}"; - } - } - - private class WorkItem - { - public RendererSynchronizationContext SynchronizationContext; - public ExecutionContext ExecutionContext; - public SendOrPostCallback Callback; - public object State; - } - - private class RendererSynchronizationTaskCompletionSource : TaskCompletionSource - { - public RendererSynchronizationTaskCompletionSource(TCallback callback) - { - Callback = callback; - } - - public TCallback Callback { get; } - } - } -} diff --git a/src/Components/Components/src/Rendering/RendererSynchronizationContextDispatcher.cs b/src/Components/Components/src/Rendering/RendererSynchronizationContextDispatcher.cs deleted file mode 100644 index e09488431c20..000000000000 --- a/src/Components/Components/src/Rendering/RendererSynchronizationContextDispatcher.cs +++ /dev/null @@ -1,66 +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.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - internal class RendererSynchronizationContextDispatcher : Dispatcher - { - private readonly RendererSynchronizationContext _context; - - public RendererSynchronizationContextDispatcher() - { - _context = new RendererSynchronizationContext(); - _context.UnhandledException += (sender, e) => - { - OnUnhandledException(e); - }; - } - - public override bool CheckAccess() => SynchronizationContext.Current == _context; - - public override Task InvokeAsync(Action workItem) - { - if (CheckAccess()) - { - workItem(); - return Task.CompletedTask; - } - - return _context.InvokeAsync(workItem); - } - - public override Task InvokeAsync(Func workItem) - { - if (CheckAccess()) - { - return workItem(); - } - - return _context.InvokeAsync(workItem); - } - - public override Task InvokeAsync(Func workItem) - { - if (CheckAccess()) - { - return Task.FromResult(workItem()); - } - - return _context.InvokeAsync(workItem); - } - - public override Task InvokeAsync(Func> workItem) - { - if (CheckAccess()) - { - return workItem(); - } - - return _context.InvokeAsync(workItem); - } - } -} diff --git a/src/Components/Components/src/RouteAttribute.cs b/src/Components/Components/src/RouteAttribute.cs deleted file mode 100644 index 6e3214845bc5..000000000000 --- a/src/Components/Components/src/RouteAttribute.cs +++ /dev/null @@ -1,33 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Indicates that the associated component should match the specified route template pattern. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public sealed class RouteAttribute : Attribute - { - /// - /// Constructs an instance of . - /// - /// The route template. - public RouteAttribute(string template) - { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - - Template = template; - } - - /// - /// Gets the route template. - /// - public string Template { get; } - } -} diff --git a/src/Components/Components/src/RouteView.cs b/src/Components/Components/src/RouteView.cs deleted file mode 100644 index 6f77169e0679..000000000000 --- a/src/Components/Components/src/RouteView.cs +++ /dev/null @@ -1,90 +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.Reflection; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Displays the specified page component, rendering it inside its layout - /// and any further nested layouts. - /// - public class RouteView : IComponent - { - private readonly RenderFragment _renderDelegate; - private readonly RenderFragment _renderPageWithParametersDelegate; - private RenderHandle _renderHandle; - - /// - /// Gets or sets the route data. This determines the page that will be - /// displayed and the parameter values that will be supplied to the page. - /// - [Parameter] - public RouteData RouteData { get; set; } - - /// - /// Gets or sets the type of a layout to be used if the page does not - /// declare any layout. If specified, the type must implement - /// and accept a parameter named . - /// - [Parameter] - public Type DefaultLayout { get; set; } - - public RouteView() - { - // Cache the delegate instances - _renderDelegate = Render; - _renderPageWithParametersDelegate = RenderPageWithParameters; - } - - /// - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - /// - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - - if (RouteData == null) - { - throw new InvalidOperationException($"The {nameof(RouteView)} component requires a non-null value for the parameter {nameof(RouteData)}."); - } - - _renderHandle.Render(_renderDelegate); - return Task.CompletedTask; - } - - /// - /// Renders the component. - /// - /// The . - protected virtual void Render(RenderTreeBuilder builder) - { - var pageLayoutType = RouteData.PageType.GetCustomAttribute()?.LayoutType - ?? DefaultLayout; - - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(LayoutView.Layout), pageLayoutType); - builder.AddAttribute(2, nameof(LayoutView.ChildContent), _renderPageWithParametersDelegate); - builder.CloseComponent(); - } - - private void RenderPageWithParameters(RenderTreeBuilder builder) - { - builder.OpenComponent(0, RouteData.PageType); - - foreach (var kvp in RouteData.RouteValues) - { - builder.AddAttribute(1, kvp.Key, kvp.Value); - } - - builder.CloseComponent(); - } - } -} diff --git a/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs b/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs deleted file mode 100644 index 89dac06e0fd8..000000000000 --- a/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs +++ /dev/null @@ -1,19 +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.Routing -{ - /// - /// An optional interface for implementations that must be initialized - /// by the host. - /// - public interface IHostEnvironmentNavigationManager - { - /// - /// Initializes the . - /// - /// The base URI. - /// The absolute URI. - void Initialize(string baseUri, string uri); - } -} diff --git a/src/Components/Components/src/Routing/INavigationInterception.cs b/src/Components/Components/src/Routing/INavigationInterception.cs deleted file mode 100644 index 0100062aba90..000000000000 --- a/src/Components/Components/src/Routing/INavigationInterception.cs +++ /dev/null @@ -1,19 +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.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components.Routing -{ - /// - /// Contract to setup navigation interception on the client. - /// - public interface INavigationInterception - { - /// - /// Enables navigation interception on the client. - /// - /// A that represents the asynchronous operation. - Task EnableNavigationInterceptionAsync(); - } -} diff --git a/src/Components/Components/src/Routing/LocationChangedEventArgs.cs b/src/Components/Components/src/Routing/LocationChangedEventArgs.cs deleted file mode 100644 index 7d1dca39e486..000000000000 --- a/src/Components/Components/src/Routing/LocationChangedEventArgs.cs +++ /dev/null @@ -1,34 +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; - -namespace Microsoft.AspNetCore.Components.Routing -{ - /// - /// for . - /// - public class LocationChangedEventArgs : EventArgs - { - /// - /// Initializes a new instance of . - /// - /// The location. - /// A value that determines if navigation for the link was intercepted. - public LocationChangedEventArgs(string location, bool isNavigationIntercepted) - { - Location = location; - IsNavigationIntercepted = isNavigationIntercepted; - } - - /// - /// Gets the changed location. - /// - public string Location { get; } - - /// - /// Gets a value that determines if navigation for the link was intercepted. - /// - public bool IsNavigationIntercepted { get; } - } -} diff --git a/src/Components/Components/src/Routing/RouteConstraint.cs b/src/Components/Components/src/Routing/RouteConstraint.cs deleted file mode 100644 index c57180fb873e..000000000000 --- a/src/Components/Components/src/Routing/RouteConstraint.cs +++ /dev/null @@ -1,81 +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.Concurrent; -using System.Globalization; - -namespace Microsoft.AspNetCore.Components.Routing -{ - internal abstract class RouteConstraint - { - // note: the things that prevent this cache from growing unbounded is that - // we're the only caller to this code path, and the fact that there are only - // 8 possible instances that we create. - // - // The values passed in here for parsing are always static text defined in route attributes. - private static readonly ConcurrentDictionary _cachedConstraints - = new ConcurrentDictionary(); - - public abstract bool Match(string pathSegment, out object convertedValue); - - public static RouteConstraint Parse(string template, string segment, string constraint) - { - if (string.IsNullOrEmpty(constraint)) - { - throw new ArgumentException($"Malformed segment '{segment}' in route '{template}' contains an empty constraint."); - } - - if (_cachedConstraints.TryGetValue(constraint, out var cachedInstance)) - { - return cachedInstance; - } - else - { - var newInstance = CreateRouteConstraint(constraint); - if (newInstance != null) - { - // We've done to the work to create the constraint now, but it's possible - // we're competing with another thread. GetOrAdd can ensure only a single - // instance is returned so that any extra ones can be GC'ed. - return _cachedConstraints.GetOrAdd(constraint, newInstance); - } - else - { - throw new ArgumentException($"Unsupported constraint '{constraint}' in route '{template}'."); - } - } - } - - private static RouteConstraint CreateRouteConstraint(string constraint) - { - switch (constraint) - { - case "bool": - return new TypeRouteConstraint(bool.TryParse); - case "datetime": - return new TypeRouteConstraint((string str, out DateTime result) - => DateTime.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.None, out result)); - case "decimal": - return new TypeRouteConstraint((string str, out decimal result) - => decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out result)); - case "double": - return new TypeRouteConstraint((string str, out double result) - => double.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out result)); - case "float": - return new TypeRouteConstraint((string str, out float result) - => float.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out result)); - case "guid": - return new TypeRouteConstraint(Guid.TryParse); - case "int": - return new TypeRouteConstraint((string str, out int result) - => int.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)); - case "long": - return new TypeRouteConstraint((string str, out long result) - => long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)); - default: - return null; - } - } - } -} diff --git a/src/Components/Components/src/Routing/RouteContext.cs b/src/Components/Components/src/Routing/RouteContext.cs deleted file mode 100644 index 7061e9be4105..000000000000 --- a/src/Components/Components/src/Routing/RouteContext.cs +++ /dev/null @@ -1,31 +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; - -namespace Microsoft.AspNetCore.Components.Routing -{ - internal class RouteContext - { - private static char[] Separator = new[] { '/' }; - - public RouteContext(string path) - { - // This is a simplification. We are assuming there are no paths like /a//b/. A proper routing - // implementation would be more sophisticated. - Segments = path.Trim('/').Split(Separator, StringSplitOptions.RemoveEmptyEntries); - // Individual segments are URL-decoded in order to support arbitrary characters, assuming UTF-8 encoding. - for (int i = 0; i < Segments.Length; i++) - { - Segments[i] = Uri.UnescapeDataString(Segments[i]); - } - } - - public string[] Segments { get; } - - public Type Handler { get; set; } - - public IReadOnlyDictionary Parameters { get; set; } - } -} diff --git a/src/Components/Components/src/Routing/RouteData.cs b/src/Components/Components/src/Routing/RouteData.cs deleted file mode 100644 index e0da00f0c747..000000000000 --- a/src/Components/Components/src/Routing/RouteData.cs +++ /dev/null @@ -1,46 +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; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Describes information determined during routing that specifies - /// the page to be displayed. - /// - public sealed class RouteData - { - /// - /// Constructs an instance of . - /// - /// The type of the page matching the route, which must implement . - /// The route parameter values extracted from the matched route. - public RouteData(Type pageType, IReadOnlyDictionary routeValues) - { - if (pageType == null) - { - throw new ArgumentNullException(nameof(pageType)); - } - - if (!typeof(IComponent).IsAssignableFrom(pageType)) - { - throw new ArgumentException($"The value must implement {nameof(IComponent)}.", nameof(pageType)); - } - - PageType = pageType; - RouteValues = routeValues ?? throw new ArgumentNullException(nameof(routeValues)); - } - - /// - /// Gets the type of the page matching the route. - /// - public Type PageType { get; } - - /// - /// Gets route parameter values extracted from the matched route. - /// - public IReadOnlyDictionary RouteValues { get; } - } -} diff --git a/src/Components/Components/src/Routing/RouteEntry.cs b/src/Components/Components/src/Routing/RouteEntry.cs deleted file mode 100644 index d2bca6d2a7ea..000000000000 --- a/src/Components/Components/src/Routing/RouteEntry.cs +++ /dev/null @@ -1,69 +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; - -namespace Microsoft.AspNetCore.Components.Routing -{ - [DebuggerDisplay("Handler = {Handler}, Template = {Template}")] - internal class RouteEntry - { - public RouteEntry(RouteTemplate template, Type handler, string[] unusedRouteParameterNames) - { - Template = template; - UnusedRouteParameterNames = unusedRouteParameterNames; - Handler = handler; - } - - public RouteTemplate Template { get; } - - public string[] UnusedRouteParameterNames { get; } - - public Type Handler { get; } - - internal void Match(RouteContext context) - { - if (Template.Segments.Length != context.Segments.Length) - { - return; - } - - // Parameters will be lazily initialized. - Dictionary parameters = null; - for (var i = 0; i < Template.Segments.Length; i++) - { - var segment = Template.Segments[i]; - var pathSegment = context.Segments[i]; - if (!segment.Match(pathSegment, out var matchedParameterValue)) - { - return; - } - else - { - if (segment.IsParameter) - { - parameters ??= new Dictionary(StringComparer.Ordinal); - parameters[segment.Value] = matchedParameterValue; - } - } - } - - // In addition to extracting parameter values from the URL, each route entry - // also knows which other parameters should be supplied with null values. These - // are parameters supplied by other route entries matching the same handler. - if (UnusedRouteParameterNames.Length > 0) - { - parameters ??= new Dictionary(StringComparer.Ordinal); - for (var i = 0; i < UnusedRouteParameterNames.Length; i++) - { - parameters[UnusedRouteParameterNames[i]] = null; - } - } - - context.Parameters = parameters; - context.Handler = Handler; - } - } -} diff --git a/src/Components/Components/src/Routing/RouteTable.cs b/src/Components/Components/src/Routing/RouteTable.cs deleted file mode 100644 index 029bc476577a..000000000000 --- a/src/Components/Components/src/Routing/RouteTable.cs +++ /dev/null @@ -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. - -namespace Microsoft.AspNetCore.Components.Routing -{ - internal class RouteTable - { - public RouteTable(RouteEntry[] routes) - { - Routes = routes; - } - - public RouteEntry[] Routes { get; } - - internal void Route(RouteContext routeContext) - { - for (var i = 0; i < Routes.Length; i++) - { - Routes[i].Match(routeContext); - if (routeContext.Handler != null) - { - return; - } - } - } - } -} diff --git a/src/Components/Components/src/Routing/RouteTableFactory.cs b/src/Components/Components/src/Routing/RouteTableFactory.cs deleted file mode 100644 index de6fe31c1d36..000000000000 --- a/src/Components/Components/src/Routing/RouteTableFactory.cs +++ /dev/null @@ -1,227 +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.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Microsoft.AspNetCore.Components.Routing; -using Microsoft.Extensions.Internal; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Resolves components for an application. - /// - internal static class RouteTableFactory - { - private static readonly ConcurrentDictionary Cache = - new ConcurrentDictionary(); - public static readonly IComparer RoutePrecedence = Comparer.Create(RouteComparison); - - public static RouteTable Create(IEnumerable assemblies) - { - var key = new Key(assemblies.OrderBy(a => a.FullName).ToArray()); - if (Cache.TryGetValue(key, out var resolvedComponents)) - { - return resolvedComponents; - } - - var componentTypes = key.Assemblies.SelectMany(a => a.ExportedTypes.Where(t => typeof(IComponent).IsAssignableFrom(t))); - var routeTable = Create(componentTypes); - Cache.TryAdd(key, routeTable); - return routeTable; - } - - internal static RouteTable Create(IEnumerable componentTypes) - { - var templatesByHandler = new Dictionary(); - foreach (var componentType in componentTypes) - { - // We're deliberately using inherit = false here. - // - // RouteAttribute is defined as non-inherited, because inheriting a route attribute always causes an - // ambiguity. You end up with two components (base class and derived class) with the same route. - var routeAttributes = componentType.GetCustomAttributes(inherit: false); - - var templates = routeAttributes.Select(t => t.Template).ToArray(); - templatesByHandler.Add(componentType, templates); - } - return Create(templatesByHandler); - } - - internal static RouteTable Create(Dictionary templatesByHandler) - { - var routes = new List(); - foreach (var keyValuePair in templatesByHandler) - { - var parsedTemplates = keyValuePair.Value.Select(v => TemplateParser.ParseTemplate(v)).ToArray(); - var allRouteParameterNames = parsedTemplates - .SelectMany(GetParameterNames) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - foreach (var parsedTemplate in parsedTemplates) - { - var unusedRouteParameterNames = allRouteParameterNames - .Except(GetParameterNames(parsedTemplate), StringComparer.OrdinalIgnoreCase) - .ToArray(); - var entry = new RouteEntry(parsedTemplate, keyValuePair.Key, unusedRouteParameterNames); - routes.Add(entry); - } - } - - return new RouteTable(routes.OrderBy(id => id, RoutePrecedence).ToArray()); - } - - private static string[] GetParameterNames(RouteTemplate routeTemplate) - { - return routeTemplate.Segments - .Where(s => s.IsParameter) - .Select(s => s.Value) - .ToArray(); - } - - /// - /// Route precedence algorithm. - /// We collect all the routes and sort them from most specific to - /// less specific. The specificity of a route is given by the specificity - /// of its segments and the position of those segments in the route. - /// * A literal segment is more specific than a parameter segment. - /// * A parameter segment with more constraints is more specific than one with fewer constraints - /// * Segment earlier in the route are evaluated before segments later in the route. - /// For example: - /// /Literal is more specific than /Parameter - /// /Route/With/{parameter} is more specific than /{multiple}/With/{parameters} - /// /Product/{id:int} is more specific than /Product/{id} - /// - /// Routes can be ambiguous if: - /// They are composed of literals and those literals have the same values (case insensitive) - /// They are composed of a mix of literals and parameters, in the same relative order and the - /// literals have the same values. - /// For example: - /// * /literal and /Literal - /// /{parameter}/literal and /{something}/literal - /// /{parameter:constraint}/literal and /{something:constraint}/literal - /// - /// To calculate the precedence we sort the list of routes as follows: - /// * Shorter routes go first. - /// * A literal wins over a parameter in precedence. - /// * For literals with different values (case insensitive) we choose the lexical order - /// * For parameters with different numbers of constraints, the one with more wins - /// If we get to the end of the comparison routing we've detected an ambiguous pair of routes. - /// - internal static int RouteComparison(RouteEntry x, RouteEntry y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - var xTemplate = x.Template; - var yTemplate = y.Template; - if (xTemplate.Segments.Length != y.Template.Segments.Length) - { - return xTemplate.Segments.Length < y.Template.Segments.Length ? -1 : 1; - } - else - { - for (var i = 0; i < xTemplate.Segments.Length; i++) - { - var xSegment = xTemplate.Segments[i]; - var ySegment = yTemplate.Segments[i]; - if (!xSegment.IsParameter && ySegment.IsParameter) - { - return -1; - } - if (xSegment.IsParameter && !ySegment.IsParameter) - { - return 1; - } - - if (xSegment.IsParameter) - { - if (xSegment.Constraints.Length > ySegment.Constraints.Length) - { - return -1; - } - else if (xSegment.Constraints.Length < ySegment.Constraints.Length) - { - return 1; - } - } - else - { - var comparison = string.Compare(xSegment.Value, ySegment.Value, StringComparison.OrdinalIgnoreCase); - if (comparison != 0) - { - return comparison; - } - } - } - - throw new InvalidOperationException($@"The following routes are ambiguous: -'{x.Template.TemplateText}' in '{x.Handler.FullName}' -'{y.Template.TemplateText}' in '{y.Handler.FullName}' -"); - } - } - - private readonly struct Key : IEquatable - { - public readonly Assembly[] Assemblies; - - public Key(Assembly[] assemblies) - { - Assemblies = assemblies; - } - - public override bool Equals(object obj) - { - return obj is Key other ? base.Equals(other) : false; - } - - public bool Equals(Key other) - { - if (Assemblies == null && other.Assemblies == null) - { - return true; - } - else if (Assemblies == null ^ other.Assemblies == null) - { - return false; - } - else if (Assemblies.Length != other.Assemblies.Length) - { - return false; - } - - for (var i = 0; i < Assemblies.Length; i++) - { - if (!Assemblies[i].Equals(other.Assemblies[i])) - { - return false; - } - } - - return true; - } - - public override int GetHashCode() - { - var hash = new HashCodeCombiner(); - - if (Assemblies != null) - { - for (var i = 0; i < Assemblies.Length; i++) - { - hash.Add(Assemblies[i]); - } - } - - return hash; - } - } - } -} diff --git a/src/Components/Components/src/Routing/RouteTemplate.cs b/src/Components/Components/src/Routing/RouteTemplate.cs deleted file mode 100644 index a79f0f911a33..000000000000 --- a/src/Components/Components/src/Routing/RouteTemplate.cs +++ /dev/null @@ -1,22 +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.Diagnostics; - -namespace Microsoft.AspNetCore.Components.Routing -{ - [DebuggerDisplay("{TemplateText}")] - internal class RouteTemplate - { - public RouteTemplate(string templateText, TemplateSegment[] segments) - { - TemplateText = templateText; - Segments = segments; - } - - public string TemplateText { get; } - - public TemplateSegment[] Segments { get; } - } -} diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs deleted file mode 100644 index b93db4b6acf4..000000000000 --- a/src/Components/Components/src/Routing/Router.cs +++ /dev/null @@ -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.Collections.ObjectModel; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Components.Routing -{ - /// - /// A component that supplies route data corresponding to the current navigation state. - /// - public class Router : IComponent, IHandleAfterRender, IDisposable - { - static readonly char[] _queryOrHashStartChar = new[] { '?', '#' }; - static readonly ReadOnlyDictionary _emptyParametersDictionary - = new ReadOnlyDictionary(new Dictionary()); - - RenderHandle _renderHandle; - string _baseUri; - string _locationAbsolute; - bool _navigationInterceptionEnabled; - ILogger _logger; - - [Inject] private NavigationManager NavigationManager { get; set; } - - [Inject] private INavigationInterception NavigationInterception { get; set; } - - [Inject] private ILoggerFactory LoggerFactory { get; set; } - - /// - /// Gets or sets the assembly that should be searched for components matching the URI. - /// - [Parameter] public Assembly AppAssembly { get; set; } - - /// - /// Gets or sets a collection of additional assemblies that should be searched for components - /// that can match URIs. - /// - [Parameter] public IEnumerable AdditionalAssemblies { get; set; } - - /// - /// Gets or sets the content to display when no match is found for the requested route. - /// - [Parameter] public RenderFragment NotFound { get; set; } - - /// - /// Gets or sets the content to display when a match is found for the requested route. - /// - [Parameter] public RenderFragment Found { get; set; } - - private RouteTable Routes { get; set; } - - /// - public void Attach(RenderHandle renderHandle) - { - _logger = LoggerFactory.CreateLogger(); - _renderHandle = renderHandle; - _baseUri = NavigationManager.BaseUri; - _locationAbsolute = NavigationManager.Uri; - NavigationManager.LocationChanged += OnLocationChanged; - } - - /// - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - - if (AppAssembly == null) - { - throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(AppAssembly)}."); - } - - // Found content is mandatory, because even though we could use something like as a - // reasonable default, if it's not declared explicitly in the template then people will have no way - // to discover how to customize this (e.g., to add authorization). - if (Found == null) - { - throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(Found)}."); - } - - // NotFound content is mandatory, because even though we could display a default message like "Not found", - // it has to be specified explicitly so that it can also be wrapped in a specific layout - if (NotFound == null) - { - throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(NotFound)}."); - } - - - var assemblies = AdditionalAssemblies == null ? new[] { AppAssembly } : new[] { AppAssembly }.Concat(AdditionalAssemblies); - Routes = RouteTableFactory.Create(assemblies); - Refresh(isNavigationIntercepted: false); - return Task.CompletedTask; - } - - /// - public void Dispose() - { - NavigationManager.LocationChanged -= OnLocationChanged; - } - - private static string StringUntilAny(string str, char[] chars) - { - var firstIndex = str.IndexOfAny(chars); - return firstIndex < 0 - ? str - : str.Substring(0, firstIndex); - } - - private void Refresh(bool isNavigationIntercepted) - { - var locationPath = NavigationManager.ToBaseRelativePath(_locationAbsolute); - locationPath = StringUntilAny(locationPath, _queryOrHashStartChar); - var context = new RouteContext(locationPath); - Routes.Route(context); - - if (context.Handler != null) - { - if (!typeof(IComponent).IsAssignableFrom(context.Handler)) - { - throw new InvalidOperationException($"The type {context.Handler.FullName} " + - $"does not implement {typeof(IComponent).FullName}."); - } - - Log.NavigatingToComponent(_logger, context.Handler, locationPath, _baseUri); - - var routeData = new RouteData( - context.Handler, - context.Parameters ?? _emptyParametersDictionary); - _renderHandle.Render(Found(routeData)); - } - else - { - if (!isNavigationIntercepted) - { - Log.DisplayingNotFound(_logger, locationPath, _baseUri); - - // We did not find a Component that matches the route. - // Only show the NotFound content if the application developer programatically got us here i.e we did not - // intercept the navigation. In all other cases, force a browser navigation since this could be non-Blazor content. - _renderHandle.Render(NotFound); - } - else - { - Log.NavigatingToExternalUri(_logger, _locationAbsolute, locationPath, _baseUri); - NavigationManager.NavigateTo(_locationAbsolute, forceLoad: true); - } - } - } - - private void OnLocationChanged(object sender, LocationChangedEventArgs args) - { - _locationAbsolute = args.Location; - if (_renderHandle.IsInitialized && Routes != null) - { - Refresh(args.IsNavigationIntercepted); - } - } - - Task IHandleAfterRender.OnAfterRenderAsync() - { - if (!_navigationInterceptionEnabled) - { - _navigationInterceptionEnabled = true; - return NavigationInterception.EnableNavigationInterceptionAsync(); - } - - return Task.CompletedTask; - } - - private static class Log - { - private static readonly Action _displayingNotFound = - LoggerMessage.Define(LogLevel.Debug, new EventId(1, "DisplayingNotFound"), $"Displaying {nameof(NotFound)} because path '{{Path}}' with base URI '{{BaseUri}}' does not match any component route"); - - private static readonly Action _navigatingToComponent = - LoggerMessage.Define(LogLevel.Debug, new EventId(2, "NavigatingToComponent"), "Navigating to component {ComponentType} in response to path '{Path}' with base URI '{BaseUri}'"); - - private static readonly Action _navigatingToExternalUri = - LoggerMessage.Define(LogLevel.Debug, new EventId(3, "NavigatingToExternalUri"), "Navigating to non-component URI '{ExternalUri}' in response to path '{Path}' with base URI '{BaseUri}'"); - - internal static void DisplayingNotFound(ILogger logger, string path, string baseUri) - { - _displayingNotFound(logger, path, baseUri, null); - } - - internal static void NavigatingToComponent(ILogger logger, Type componentType, string path, string baseUri) - { - _navigatingToComponent(logger, componentType, path, baseUri, null); - } - - internal static void NavigatingToExternalUri(ILogger logger, string externalUri, string path, string baseUri) - { - _navigatingToExternalUri(logger, externalUri, path, baseUri, null); - } - } - } -} diff --git a/src/Components/Components/src/Routing/TemplateParser.cs b/src/Components/Components/src/Routing/TemplateParser.cs deleted file mode 100644 index d4563ebf7fd7..000000000000 --- a/src/Components/Components/src/Routing/TemplateParser.cs +++ /dev/null @@ -1,108 +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; - -namespace Microsoft.AspNetCore.Components.Routing -{ - // This implementation is temporary, in the future we'll want to have - // a more performant/properly designed routing set of abstractions. - // To be more precise these are some things we are scoping out: - // * We are not doing link generation. - // * We are not supporting all the route constraint formats supported by ASP.NET server-side routing. - // The class in here just takes care of parsing a route and extracting - // simple parameters from it. - // Some differences with ASP.NET Core routes are: - // * We don't support catch all parameter segments. - // * We don't support optional parameter segments. - // * We don't support complex segments. - // The things that we support are: - // * Literal path segments. (Like /Path/To/Some/Page) - // * Parameter path segments (Like /Customer/{Id}/Orders/{OrderId}) - internal class TemplateParser - { - public static readonly char[] InvalidParameterNameCharacters = - new char[] { '*', '?', '{', '}', '=', '.' }; - - internal static RouteTemplate ParseTemplate(string template) - { - var originalTemplate = template; - template = template.Trim('/'); - if (template == "") - { - // Special case "/"; - return new RouteTemplate("/", Array.Empty()); - } - - var segments = template.Split('/'); - var templateSegments = new TemplateSegment[segments.Length]; - for (int i = 0; i < segments.Length; i++) - { - var segment = segments[i]; - if (string.IsNullOrEmpty(segment)) - { - throw new InvalidOperationException( - $"Invalid template '{template}'. Empty segments are not allowed."); - } - - if (segment[0] != '{') - { - if (segment[segment.Length - 1] == '}') - { - throw new InvalidOperationException( - $"Invalid template '{template}'. Missing '{{' in parameter segment '{segment}'."); - } - templateSegments[i] = new TemplateSegment(originalTemplate, segment, isParameter: false); - } - else - { - if (segment[segment.Length - 1] != '}') - { - throw new InvalidOperationException( - $"Invalid template '{template}'. Missing '}}' in parameter segment '{segment}'."); - } - - if (segment.Length < 3) - { - throw new InvalidOperationException( - $"Invalid template '{template}'. Empty parameter name in segment '{segment}' is not allowed."); - } - - var invalidCharacter = segment.IndexOfAny(InvalidParameterNameCharacters, 1, segment.Length - 2); - if (invalidCharacter != -1) - { - throw new InvalidOperationException( - $"Invalid template '{template}'. The character '{segment[invalidCharacter]}' in parameter segment '{segment}' is not allowed."); - } - - templateSegments[i] = new TemplateSegment(originalTemplate, segment.Substring(1, segment.Length - 2), isParameter: true); - } - } - - for (int i = 0; i < templateSegments.Length; i++) - { - var currentSegment = templateSegments[i]; - if (!currentSegment.IsParameter) - { - continue; - } - - for (int j = i + 1; j < templateSegments.Length; j++) - { - var nextSegment = templateSegments[j]; - if (!nextSegment.IsParameter) - { - continue; - } - - if (string.Equals(currentSegment.Value, nextSegment.Value, StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidOperationException( - $"Invalid template '{template}'. The parameter '{currentSegment}' appears multiple times."); - } - } - } - - return new RouteTemplate(template, templateSegments); - } - } -} diff --git a/src/Components/Components/src/Routing/TemplateSegment.cs b/src/Components/Components/src/Routing/TemplateSegment.cs deleted file mode 100644 index 9f732598dbbe..000000000000 --- a/src/Components/Components/src/Routing/TemplateSegment.cs +++ /dev/null @@ -1,66 +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; - -namespace Microsoft.AspNetCore.Components.Routing -{ - internal class TemplateSegment - { - public TemplateSegment(string template, string segment, bool isParameter) - { - IsParameter = isParameter; - - if (!isParameter || segment.IndexOf(':') < 0) - { - Value = segment; - Constraints = Array.Empty(); - } - else - { - var tokens = segment.Split(':'); - if (tokens[0].Length == 0) - { - throw new ArgumentException($"Malformed parameter '{segment}' in route '{template}' has no name before the constraints list."); - } - - Value = tokens[0]; - Constraints = tokens.Skip(1) - .Select(token => RouteConstraint.Parse(template, segment, token)) - .ToArray(); - } - } - - // The value of the segment. The exact text to match when is a literal. - // The parameter name when its a segment - public string Value { get; } - - public bool IsParameter { get; } - - public RouteConstraint[] Constraints { get; } - - public bool Match(string pathSegment, out object matchedParameterValue) - { - if (IsParameter) - { - matchedParameterValue = pathSegment; - - foreach (var constraint in Constraints) - { - if (!constraint.Match(pathSegment, out matchedParameterValue)) - { - return false; - } - } - - return true; - } - else - { - matchedParameterValue = null; - return string.Equals(Value, pathSegment, StringComparison.OrdinalIgnoreCase); - } - } - } -} diff --git a/src/Components/Components/src/Routing/TypeRouteConstraint.cs b/src/Components/Components/src/Routing/TypeRouteConstraint.cs deleted file mode 100644 index 1026e88eac41..000000000000 --- a/src/Components/Components/src/Routing/TypeRouteConstraint.cs +++ /dev/null @@ -1,35 +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.Routing -{ - /// - /// A route constraint that requires the value to be parseable as a specified type. - /// - /// The type to which the value must be parseable. - internal class TypeRouteConstraint : RouteConstraint - { - public delegate bool TryParseDelegate(string str, out T result); - - private readonly TryParseDelegate _parser; - - public TypeRouteConstraint(TryParseDelegate parser) - { - _parser = parser; - } - - public override bool Match(string pathSegment, out object convertedValue) - { - if (_parser(pathSegment, out var result)) - { - convertedValue = result; - return true; - } - else - { - convertedValue = null; - return false; - } - } - } -} diff --git a/src/Components/Components/test/BindConverterTest.cs b/src/Components/Components/test/BindConverterTest.cs deleted file mode 100644 index c6fe1275cc77..000000000000 --- a/src/Components/Components/test/BindConverterTest.cs +++ /dev/null @@ -1,307 +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.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Text.Json; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - // This is some basic coverage, it's not in depth because there are many many APIs here - // and they mostly call through to CoreFx. We don't want to test the globalization details - // of .NET in detail where we can avoid it. - // - // Instead there's a sampling of things that have somewhat unique behavior or semantics. - public class BindConverterTest - { - [Fact] - public void FormatValue_Bool() - { - // Arrange - var value = true; - var expected = true; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_Bool_Generic() - { - // Arrange - var value = true; - var expected = true; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableBool() - { - // Arrange - var value = (bool?)true; - var expected = true; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableBool_Generic() - { - // Arrange - var value = true; - var expected = true; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableBoolNull() - { - // Arrange - var value = (bool?)null; - var expected = (bool?)null; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableBoolNull_Generic() - { - // Arrange - var value = (bool?)null; - var expected = (bool?)null; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_Int() - { - // Arrange - var value = 17; - var expected = "17"; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_Int_Generic() - { - // Arrange - var value = 17; - var expected = "17"; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableInt() - { - // Arrange - var value = (int?)17; - var expected = "17"; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableInt_Generic() - { - // Arrange - var value = 17; - var expected = "17"; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_DateTime() - { - // Arrange - var value = DateTime.Now; - var expected = value.ToString(CultureInfo.CurrentCulture); - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_DateTime_Format() - { - // Arrange - var value = DateTime.Now; - var expected = value.ToString("MM-yyyy", CultureInfo.InvariantCulture); - - // Act - var actual = BindConverter.FormatValue(value, "MM-yyyy", CultureInfo.InvariantCulture); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_Enum() - { - // Arrange - var value = SomeLetters.A; - var expected = value.ToString(); - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_Enum_OutOfRange() - { - // Arrange - var value = SomeLetters.A + 3; - var expected = value.ToString(); - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - [Fact] - public void FormatValue_NullableEnum() - { - // Arrange - var value = (SomeLetters?)null; - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Null(actual); - } - - [Fact] - public void FormatValue_TypeConverter() - { - // Arrange - var value = new Person() - { - Name = "Glenn", - Age = 47, - }; - - var expected = JsonSerializer.Serialize(value); - - // Act - var actual = BindConverter.FormatValue(value); - - // Assert - Assert.Equal(expected, actual); - } - - private enum SomeLetters - { - A, - B, - C, - Q, - } - - [TypeConverter(typeof(PersonConverter))] - private class Person - { - public string Name { get; set; } - - public int Age { get; set; } - } - - private class PersonConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - - return base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string text) - { - return JsonSerializer.Deserialize(text); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - - return base.CanConvertTo(context, destinationType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == typeof(string)) - { - return JsonSerializer.Serialize((Person)value); - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } -} diff --git a/src/Components/Components/test/CascadingParameterStateTest.cs b/src/Components/Components/test/CascadingParameterStateTest.cs deleted file mode 100644 index 5931d9d6fc70..000000000000 --- a/src/Components/Components/test/CascadingParameterStateTest.cs +++ /dev/null @@ -1,442 +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; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.Test.Helpers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class CascadingParameterStateTest - { - [Fact] - public void FindCascadingParameters_IfHasNoParameters_ReturnsNull() - { - // Arrange - var componentState = CreateComponentState(new ComponentWithNoParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(componentState); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_IfHasNoCascadingParameters_ReturnsNull() - { - // Arrange - var componentState = CreateComponentState(new ComponentWithNoCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(componentState); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_IfHasNoAncestors_ReturnsNull() - { - // Arrange - var componentState = CreateComponentState(new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(componentState); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_IfHasNoMatchesInAncestors_ReturnsNull() - { - // Arrange: Build the ancestry list - var states = CreateAncestry( - new ComponentWithNoParams(), - CreateCascadingValueComponent("Hello"), - new ComponentWithNoParams(), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_IfHasPartialMatchesInAncestors_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - new ComponentWithNoParams(), - CreateCascadingValueComponent(new ValueType2()), - new ComponentWithNoParams(), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result, match => - { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam2), match.LocalValueName); - Assert.Same(states[1].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_IfHasMultipleMatchesInAncestors_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - new ComponentWithNoParams(), - CreateCascadingValueComponent(new ValueType2()), - new ComponentWithNoParams(), - CreateCascadingValueComponent(new ValueType1()), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result.OrderBy(x => x.LocalValueName), - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam1), match.LocalValueName); - Assert.Same(states[3].Component, match.ValueSupplier); - }, - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam2), match.LocalValueName); - Assert.Same(states[1].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_InheritedParameters_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1()), - CreateCascadingValueComponent(new ValueType3()), - new ComponentWithInheritedCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result.OrderBy(x => x.LocalValueName), - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam1), match.LocalValueName); - Assert.Same(states[0].Component, match.ValueSupplier); - }, - match => { - Assert.Equal(nameof(ComponentWithInheritedCascadingParams.CascadingParam3), match.LocalValueName); - Assert.Same(states[1].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_ComponentRequestsBaseType_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new CascadingValueTypeDerivedClass()), - new ComponentWithGenericCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result, match => { - Assert.Equal(nameof(ComponentWithGenericCascadingParam.LocalName), match.LocalValueName); - Assert.Same(states[0].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_ComponentRequestsImplementedInterface_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new CascadingValueTypeDerivedClass()), - new ComponentWithGenericCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result, match => { - Assert.Equal(nameof(ComponentWithGenericCascadingParam.LocalName), match.LocalValueName); - Assert.Same(states[0].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_ComponentRequestsDerivedType_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new CascadingValueTypeBaseClass()), - new ComponentWithGenericCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_TypeAssignmentIsValidForNullValue_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent((CascadingValueTypeDerivedClass)null), - new ComponentWithGenericCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result, match => { - Assert.Equal(nameof(ComponentWithGenericCascadingParam.LocalName), match.LocalValueName); - Assert.Same(states[0].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_TypeAssignmentIsInvalidForNullValue_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent((object)null), - new ComponentWithGenericCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_SupplierSpecifiesNameButConsumerDoesNot_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1(), "MatchOnName"), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_ConsumerSpecifiesNameButSupplierDoesNot_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1()), - new ComponentWithNamedCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_MismatchingNameButMatchingType_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1(), "MismatchName"), - new ComponentWithNamedCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_MatchingNameButMismatchingType_ReturnsNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType2(), "MatchOnName"), - new ComponentWithNamedCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Null(result); - } - - [Fact] - public void FindCascadingParameters_MatchingNameAndType_ReturnsMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1(), "matchonNAME"), // To show it's case-insensitive - new ComponentWithNamedCascadingParam()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result, match => { - Assert.Equal(nameof(ComponentWithNamedCascadingParam.SomeLocalName), match.LocalValueName); - Assert.Same(states[0].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_MultipleMatchingAncestors_ReturnsClosestMatches() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1()), - CreateCascadingValueComponent(new ValueType2()), - CreateCascadingValueComponent(new ValueType1()), - CreateCascadingValueComponent(new ValueType2()), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result.OrderBy(x => x.LocalValueName), - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam1), match.LocalValueName); - Assert.Same(states[2].Component, match.ValueSupplier); - }, - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam2), match.LocalValueName); - Assert.Same(states[3].Component, match.ValueSupplier); - }); - } - - [Fact] - public void FindCascadingParameters_CanOverrideNonNullValueWithNull() - { - // Arrange - var states = CreateAncestry( - CreateCascadingValueComponent(new ValueType1()), - CreateCascadingValueComponent((ValueType1)null), - new ComponentWithCascadingParams()); - - // Act - var result = CascadingParameterState.FindCascadingParameters(states.Last()); - - // Assert - Assert.Collection(result.OrderBy(x => x.LocalValueName), - match => { - Assert.Equal(nameof(ComponentWithCascadingParams.CascadingParam1), match.LocalValueName); - Assert.Same(states[1].Component, match.ValueSupplier); - Assert.Null(match.ValueSupplier.CurrentValue); - }); - } - - static ComponentState[] CreateAncestry(params IComponent[] components) - { - var result = new ComponentState[components.Length]; - - for (var i = 0; i < components.Length; i++) - { - result[i] = CreateComponentState( - components[i], - i == 0 ? null : result[i - 1]); - } - - return result; - } - - static ComponentState CreateComponentState( - IComponent component, ComponentState parentComponentState = null) - { - return new ComponentState(new TestRenderer(), 0, component, parentComponentState); - } - - static CascadingValue CreateCascadingValueComponent(T value, string name = null) - { - var supplier = new CascadingValue(); - var renderer = new TestRenderer(); - supplier.Attach(new RenderHandle(renderer, 0)); - - var supplierParams = new Dictionary - { - { "Value", value } - }; - - if (name != null) - { - supplierParams.Add("Name", name); - } - - renderer.Dispatcher.InvokeAsync((Action)(() => supplier.SetParametersAsync(ParameterView.FromDictionary(supplierParams)))); - return supplier; - } - - class ComponentWithNoParams : TestComponentBase - { - } - - class ComponentWithNoCascadingParams : TestComponentBase - { - [Parameter] public bool SomeRegularParameter { get; set; } - } - - class ComponentWithCascadingParams : TestComponentBase - { - [Parameter] public bool RegularParam { get; set; } - [CascadingParameter] internal ValueType1 CascadingParam1 { get; set; } - [CascadingParameter] internal ValueType2 CascadingParam2 { get; set; } - } - - class ComponentWithInheritedCascadingParams : ComponentWithCascadingParams - { - [CascadingParameter] internal ValueType3 CascadingParam3 { get; set; } - } - - class ComponentWithGenericCascadingParam : TestComponentBase - { - [CascadingParameter] internal T LocalName { get; set; } - } - - class ComponentWithNamedCascadingParam : TestComponentBase - { - [CascadingParameter(Name = "MatchOnName")] - internal ValueType1 SomeLocalName { get; set; } - } - - class TestComponentBase : IComponent - { - public void Attach(RenderHandle renderHandle) - => throw new NotImplementedException(); - - public Task SetParametersAsync(ParameterView parameters) - => throw new NotImplementedException(); - } - - class ValueType1 { } - class ValueType2 { } - class ValueType3 { } - - class CascadingValueTypeBaseClass { } - class CascadingValueTypeDerivedClass : CascadingValueTypeBaseClass, ICascadingValueTypeDerivedClassInterface { } - interface ICascadingValueTypeDerivedClassInterface { } - } -} diff --git a/src/Components/Components/test/CascadingParameterTest.cs b/src/Components/Components/test/CascadingParameterTest.cs deleted file mode 100644 index a9066647414b..000000000000 --- a/src/Components/Components/test/CascadingParameterTest.cs +++ /dev/null @@ -1,449 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class CascadingParameterTest - { - [Fact] - public void PassesCascadingParametersToNestedComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", "Hello"); - builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent>(0); - childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(batch, out var nestedComponentId); - var nestedComponentDiff = batch.DiffsByComponentId[nestedComponentId].Single(); - - // The nested component was rendered with the correct parameters - Assert.Collection(nestedComponentDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "CascadingParameter=Hello; RegularParameter=Goodbye"); - }); - Assert.Equal(1, nestedComponent.NumRenders); - } - - [Fact] - public void RetainsCascadingParametersWhenUpdatingDirectParameters() - { - // Arrange - var renderer = new TestRenderer(); - var regularParameterValue = "Initial value"; - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", "Hello"); - builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent>(0); - childBuilder.AddAttribute(1, "RegularParameter", regularParameterValue); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Act 1: Render in initial state - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Capture the nested component so we can verify the update later - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out var nestedComponentId); - Assert.Equal(1, nestedComponent.NumRenders); - - // Act 2: Render again with updated regular parameter - regularParameterValue = "Changed value"; - component.TriggerRender(); - - // Assert - Assert.Equal(2, renderer.Batches.Count); - var secondBatch = renderer.Batches[1]; - var nestedComponentDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single(); - - // The nested component was rendered with the correct parameters - Assert.Collection(nestedComponentDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); // This is the only change - AssertFrame.Text(secondBatch.ReferenceFrames[0], "CascadingParameter=Hello; RegularParameter=Changed value"); - }); - Assert.Equal(2, nestedComponent.NumRenders); - } - - [Fact] - public void NotifiesDescendantsOfUpdatedCascadingParameterValuesAndPreservesDirectParameters() - { - // Arrange - var providedValue = "Initial value"; - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", providedValue); - builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent>(0); - childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Act 1: Initial render; capture nested component ID - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out var nestedComponentId); - Assert.Equal(1, nestedComponent.NumRenders); - - // Act 2: Re-render CascadingValue with new value - providedValue = "Updated value"; - component.TriggerRender(); - - // Assert: We re-rendered CascadingParameterConsumerComponent - Assert.Equal(2, renderer.Batches.Count); - var secondBatch = renderer.Batches[1]; - var nestedComponentDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single(); - - // The nested component was rendered with the correct parameters - Assert.Collection(nestedComponentDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); // This is the only change - AssertFrame.Text(secondBatch.ReferenceFrames[0], "CascadingParameter=Updated value; RegularParameter=Goodbye"); - }); - Assert.Equal(2, nestedComponent.NumRenders); - } - - [Fact] - public void DoesNotNotifyDescendantsIfCascadingParameterValuesAreImmutableAndUnchanged() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", "Unchanging value"); - builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent>(0); - childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Act 1: Initial render - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out _); - Assert.Equal(3, firstBatch.DiffsByComponentId.Count); // Root + CascadingValue + nested - Assert.Equal(1, nestedComponent.NumRenders); - - // Act/Assert: Re-render the CascadingValue; observe nested component wasn't re-rendered - component.TriggerRender(); - - // Assert: We did not re-render CascadingParameterConsumerComponent - Assert.Equal(2, renderer.Batches.Count); - var secondBatch = renderer.Batches[1]; - Assert.Equal(2, secondBatch.DiffsByComponentId.Count); // Root + CascadingValue, but not nested one - Assert.Equal(1, nestedComponent.NumRenders); - } - - [Fact] - public void StopsNotifyingDescendantsIfTheyAreRemoved() - { - // Arrange - var providedValue = "Initial value"; - var displayNestedComponent = true; - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - // At the outer level, have an unrelated fixed cascading value to show we can deal with combining both types - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", 123); - builder.AddAttribute(2, "IsFixed", true); - builder.AddAttribute(3, "ChildContent", new RenderFragment(builder2 => - { - // Then also have a non-fixed cascading value so we can show that unsubscription works - builder2.OpenComponent>(0); - builder2.AddAttribute(1, "Value", providedValue); - builder2.AddAttribute(2, "ChildContent", new RenderFragment(builder3 => - { - if (displayNestedComponent) - { - builder3.OpenComponent>(0); - builder3.AddAttribute(1, "RegularParameter", "Goodbye"); - builder3.CloseComponent(); - } - })); - builder2.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Act 1: Initial render; capture nested component ID - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out var nestedComponentId); - Assert.Equal(1, nestedComponent.NumSetParametersCalls); - Assert.Equal(1, nestedComponent.NumRenders); - - // Act/Assert 2: Re-render the CascadingValue; observe nested component wasn't re-rendered - providedValue = "Updated value"; - displayNestedComponent = false; // Remove the nested componet - component.TriggerRender(); - - // Assert: We did not render the nested component now it's been removed - Assert.Equal(2, renderer.Batches.Count); - var secondBatch = renderer.Batches[1]; - Assert.Equal(1, nestedComponent.NumRenders); - Assert.Equal(3, secondBatch.DiffsByComponentId.Count); // Root + CascadingValue + CascadingValue, but not nested component - - // We *did* send updated params during the first render where it was removed, - // because the params are sent before the disposal logic runs. We could avoid - // this by moving the notifications into the OnAfterRender phase, but then we'd - // often render descendants twice (once because they are descendants and some - // direct parameter might have changed, then once because a cascading parameter - // changed). We can't have it both ways, so optimize for the case when the - // nested component *hasn't* just been removed. - Assert.Equal(2, nestedComponent.NumSetParametersCalls); - - // Act 3: However, after disposal, the subscription is removed, so we won't send - // updated params on subsequent CascadingValue renders. - providedValue = "Updated value 2"; - component.TriggerRender(); - Assert.Equal(2, nestedComponent.NumSetParametersCalls); - } - - [Fact] - public void DoesNotNotifyDescendantsOfUpdatedCascadingParameterValuesWhenFixed() - { - // Arrange - var providedValue = "Initial value"; - var shouldIncludeChild = true; - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", providedValue); - builder.AddAttribute(2, "IsFixed", true); - builder.AddAttribute(3, "ChildContent", new RenderFragment(childBuilder => - { - if (shouldIncludeChild) - { - childBuilder.OpenComponent>(0); - childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); - childBuilder.CloseComponent(); - } - })); - builder.CloseComponent(); - }); - - // Act 1: Initial render; capture nested component ID - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out var nestedComponentId); - Assert.Equal(1, nestedComponent.NumRenders); - - // Assert: Initial value is supplied to descendant - var nestedComponentDiff = firstBatch.DiffsByComponentId[nestedComponentId].Single(); - Assert.Collection(nestedComponentDiff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - firstBatch.ReferenceFrames[edit.ReferenceFrameIndex], - "CascadingParameter=Initial value; RegularParameter=Goodbye"); - }); - - // Act 2: Re-render CascadingValue with new value - providedValue = "Updated value"; - component.TriggerRender(); - - // Assert: We did not re-render the descendant - Assert.Equal(2, renderer.Batches.Count); - var secondBatch = renderer.Batches[1]; - Assert.Equal(2, secondBatch.DiffsByComponentId.Count); // Root + CascadingValue, but not nested one - Assert.Equal(1, nestedComponent.NumSetParametersCalls); - Assert.Equal(1, nestedComponent.NumRenders); - - // Act 3: Dispose - shouldIncludeChild = false; - component.TriggerRender(); - - // Assert: Absence of an exception here implies we didn't cause a problem by - // trying to remove a non-existent subscription - } - - [Fact] - public void CascadingValueThrowsIfFixedFlagChangesToTrue() - { - // Arrange - var renderer = new TestRenderer(); - var isFixed = false; - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "IsFixed", isFixed); - builder.AddAttribute(2, "Value", new object()); - builder.CloseComponent(); - }); - renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Act/Assert - isFixed = true; - var ex = Assert.Throws(() => component.TriggerRender()); - Assert.Equal("The value of IsFixed cannot be changed dynamically.", ex.Message); - } - - [Fact] - public void CascadingValueThrowsIfFixedFlagChangesToFalse() - { - // Arrange - var renderer = new TestRenderer(); - var isFixed = true; - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - if (isFixed) // Showing also that "unset" is treated as "false" - { - builder.AddAttribute(1, "IsFixed", true); - } - builder.AddAttribute(2, "Value", new object()); - builder.CloseComponent(); - }); - renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Act/Assert - isFixed = false; - var ex = Assert.Throws(() => component.TriggerRender()); - Assert.Equal("The value of IsFixed cannot be changed dynamically.", ex.Message); - } - - [Fact] - public void ParameterViewSuppliedWithCascadingParametersCannotBeUsedAfterSynchronousReturn() - { - // Arrange - var providedValue = "Initial value"; - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent>(0); - builder.AddAttribute(1, "Value", providedValue); - builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => - { - childBuilder.OpenComponent>(0); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - }); - - // Initial render; capture nested component - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var firstBatch = renderer.Batches.Single(); - var nestedComponent = FindComponent>(firstBatch, out var nestedComponentId); - - // Re-render CascadingValue with new value, so it gets a new ParameterView - providedValue = "Updated value"; - component.TriggerRender(); - Assert.Equal(2, renderer.Batches.Count); - - // It's no longer able to access anything in the ParameterView it just received - var ex = Assert.Throws(nestedComponent.AttemptIllegalAccessToLastParameterView); - Assert.Equal($"The {nameof(ParameterView)} instance can no longer be read because it has expired. {nameof(ParameterView)} can only be read synchronously and must not be stored for later use.", ex.Message); - } - - private static T FindComponent(CapturedBatch batch, out int componentId) - { - var componentFrame = batch.ReferenceFrames.Single( - frame => frame.FrameType == RenderTreeFrameType.Component - && frame.Component is T); - componentId = componentFrame.ComponentId; - return (T)componentFrame.Component; - } - - class TestComponent : AutoRenderComponent - { - private readonly RenderFragment _renderFragment; - - public TestComponent(RenderFragment renderFragment) - { - _renderFragment = renderFragment; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - => _renderFragment(builder); - } - - class CascadingParameterConsumerComponent : AutoRenderComponent - { - private ParameterView lastParameterView; - - public int NumSetParametersCalls { get; private set; } - public int NumRenders { get; private set; } - - [CascadingParameter] T CascadingParameter { get; set; } - [Parameter] public string RegularParameter { get; set; } - - public override async Task SetParametersAsync(ParameterView parameters) - { - lastParameterView = parameters; - NumSetParametersCalls++; - await base.SetParametersAsync(parameters); - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - NumRenders++; - builder.AddContent(0, $"CascadingParameter={CascadingParameter}; RegularParameter={RegularParameter}"); - } - - public void AttemptIllegalAccessToLastParameterView() - { - // You're not allowed to hold onto a ParameterView and access it later, - // so this should throw - lastParameterView.TryGetValue("anything", out _); - } - } - - class SecondCascadingParameterConsumerComponent : CascadingParameterConsumerComponent - { - [CascadingParameter] T2 SecondCascadingParameter { get; set; } - } - } -} diff --git a/src/Components/Components/test/ComponentBaseTest.cs b/src/Components/Components/test/ComponentBaseTest.cs deleted file mode 100644 index bd09cc49c559..000000000000 --- a/src/Components/Components/test/ComponentBaseTest.cs +++ /dev/null @@ -1,581 +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.Diagnostics; -using System.Reflection.Metadata.Ecma335; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class ComponentBaseTest - { - // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch - // failures. - private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10); - - [Fact] - public void RunsOnInitWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onInitRuns = 0; - component.OnInitLogic = c => onInitRuns++; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onInitRuns); - } - - [Fact] - public void RunsOnInitAsyncWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onInitAsyncRuns = 0; - component.RunsBaseOnInitAsync = false; - component.OnInitAsyncLogic = c => - { - onInitAsyncRuns++; - return Task.CompletedTask; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onInitAsyncRuns); - Assert.Single(renderer.Batches); - } - - [Fact] - public void RunsOnInitAsyncAlsoOnBaseClassWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onInitAsyncRuns = 0; - component.RunsBaseOnInitAsync = true; - component.OnInitAsyncLogic = c => - { - onInitAsyncRuns++; - return Task.CompletedTask; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onInitAsyncRuns); - Assert.Single(renderer.Batches); - } - - [Fact] - public void RunsOnParametersSetWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onParametersSetRuns = 0; - component.OnParametersSetLogic = c => onParametersSetRuns++; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onParametersSetRuns); - Assert.Single(renderer.Batches); - } - - [Fact] - public void RunsOnParametersSetAsyncWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onParametersSetAsyncRuns = 0; - component.RunsBaseOnParametersSetAsync = false; - component.OnParametersSetAsyncLogic = c => - { - onParametersSetAsyncRuns++; - return Task.CompletedTask; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onParametersSetAsyncRuns); - Assert.Single(renderer.Batches); - } - - [Fact] - public void RunsOnParametersSetAsyncAlsoOnBaseClassWhenRendered() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - var onParametersSetAsyncRuns = 0; - component.RunsBaseOnParametersSetAsync = true; - component.OnParametersSetAsyncLogic = c => - { - onParametersSetAsyncRuns++; - return Task.CompletedTask; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - renderer.RenderRootComponent(componentId); - - // Assert - Assert.Equal(1, onParametersSetAsyncRuns); - Assert.Single(renderer.Batches); - } - - [Fact] - public async Task RendersAfterParametersSetAsyncTaskIsCompleted() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(); - - component.Counter = 1; - var parametersSetTask = new TaskCompletionSource(); - component.RunsBaseOnParametersSetAsync = false; - component.OnParametersSetAsyncLogic = c => parametersSetTask.Task; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - Assert.Single(renderer.Batches); - - // Completes task started by OnParametersSetAsync - component.Counter = 2; - parametersSetTask.SetResult(true); - - await renderTask; - - // Component should be rendered again - Assert.Equal(2, renderer.Batches.Count); - } - - [Fact] - public async Task RendersAfterParametersSetAndInitAsyncTasksAreCompleted() - { - // Arrange - var @event = new ManualResetEventSlim(); - - var renderer = new TestRenderer() - { - OnUpdateDisplayComplete = () => { @event.Set(); }, - }; - var component = new TestComponent(); - - component.Counter = 1; - var initTask = new TaskCompletionSource(); - var parametersSetTask = new TaskCompletionSource(); - component.RunsBaseOnInitAsync = true; - component.RunsBaseOnParametersSetAsync = true; - component.OnInitAsyncLogic = c => initTask.Task; - component.OnParametersSetAsyncLogic = c => parametersSetTask.Task; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - // A rendering should have happened after the synchronous execution of Init - Assert.Single(renderer.Batches); - - @event.Reset(); - - // Completes task started by OnInitAsync - component.Counter = 2; - initTask.SetResult(true); - - // We need to wait here, because the continuation from SetResult needs to be scheduled. - @event.Wait(Timeout); - @event.Reset(); - - // Component should be rendered once, after set parameters - Assert.Equal(2, renderer.Batches.Count); - - // Completes task started by OnParametersSetAsync - component.Counter = 3; - parametersSetTask.SetResult(false); - - await renderTask; - Assert.True(@event.IsSet); - - // Component should be rendered again - // after the async part of onparameterssetasync completes - Assert.Equal(3, renderer.Batches.Count); - } - - [Fact] - public async Task DoesNotRenderAfterOnInitAsyncTaskIsCancelled() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent() { Counter = 1 }; - var initTask = new TaskCompletionSource(); - component.OnInitAsyncLogic = _ => initTask.Task; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - Assert.False(renderTask.IsCompleted); - Assert.Single(renderer.Batches); - - // Cancel task started by OnInitAsync - component.Counter = 2; - initTask.SetCanceled(); - - await renderTask; - - // Component should only be rendered again due to - // the call to StateHasChanged after SetParametersAsync - Assert.Equal(2, renderer.Batches.Count); - } - - [Fact] - public async Task RunsOnAfterRender_AfterRenderingCompletes() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent() { Counter = 1 }; - - var onAfterRenderCompleted = false; - component.OnAfterRenderLogic = (c, firstRender) => - { - Assert.True(firstRender); - Assert.Single(renderer.Batches); - onAfterRenderCompleted = true; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - await renderTask; - Assert.True(onAfterRenderCompleted); - - // Component should not be rendered again. OnAfterRender doesn't do that. - Assert.Single(renderer.Batches); - - // Act: Render again! - onAfterRenderCompleted = false; - component.OnAfterRenderLogic = (c, firstRender) => - { - Assert.False(firstRender); - Assert.Equal(2, renderer.Batches.Count); - onAfterRenderCompleted = true; - }; - - renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - Assert.True(onAfterRenderCompleted); - Assert.Equal(2, renderer.Batches.Count); - await renderTask; - } - - [Fact] - public async Task RunsOnAfterRenderAsync_AfterRenderingCompletes() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent() { Counter = 1 }; - - var onAfterRenderCompleted = false; - var tcs = new TaskCompletionSource(); - component.OnAfterRenderAsyncLogic = async (c, firstRender) => - { - Assert.True(firstRender); - Assert.Single(renderer.Batches); - onAfterRenderCompleted = true; - await tcs.Task; - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - tcs.SetResult(null); - await renderTask; - Assert.True(onAfterRenderCompleted); - - // Component should not be rendered again. OnAfterRenderAsync doesn't do that. - Assert.Single(renderer.Batches); - - // Act: Render again! - onAfterRenderCompleted = false; - tcs = new TaskCompletionSource(); - component.OnAfterRenderAsyncLogic = async (c, firstRender) => - { - Assert.False(firstRender); - Assert.Equal(2, renderer.Batches.Count); - onAfterRenderCompleted = true; - await tcs.Task; - }; - - renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - tcs.SetResult(null); - await renderTask; - Assert.True(onAfterRenderCompleted); - Assert.Equal(2, renderer.Batches.Count); - } - - [Fact] - public async Task DoesNotRenderAfterOnInitAsyncTaskIsCancelledUsingCancellationToken() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent() { Counter = 1 }; - - var cts = new CancellationTokenSource(); - cts.Cancel(); - component.OnInitAsyncLogic = async _ => - { - await Task.Yield(); - cts.Token.ThrowIfCancellationRequested(); - }; - - // Act - var componentId = renderer.AssignRootComponentId(component); - await renderer.RenderRootComponentAsync(componentId); - - // Assert - // At least one call to StateHasChanged depending on how OnInitAsyncLogic gets scheduled. - Assert.NotEmpty(renderer.Batches); - } - - [Fact] - public async Task DoesNotRenderAfterOnParametersSetAsyncTaskIsCanceled() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent() { Counter = 1 }; - var onParametersSetTask = new TaskCompletionSource(); - component.OnParametersSetAsyncLogic = _ => onParametersSetTask.Task; - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - // Assert - Assert.Single(renderer.Batches); - - // Cancel task started by OnParametersSet - component.Counter = 2; - onParametersSetTask.SetCanceled(); - - await renderTask; - - // Component should not be rendered again - Assert.Single(renderer.Batches); - - } - - [Fact] - public async Task RenderRootComponentAsync_ReportsErrorDuringOnInit() - { - // Arrange - var expected = new TimeZoneNotFoundException(); - var renderer = new TestRenderer(); - var component = new TestComponent { OnInitLogic = _ => throw expected }; - - // Act & Assert - var componentId = renderer.AssignRootComponentId(component); - var actual = await Assert.ThrowsAsync(() => renderer.RenderRootComponentAsync(componentId)); - - // Assert - Assert.Same(expected, actual); - } - - [Fact] - public async Task RenderRootComponentAsync_ReportsErrorDuringOnInitAsync() - { - // Arrange - var expected = new TimeZoneNotFoundException(); - var renderer = new TestRenderer(); - var component = new TestComponent { OnInitAsyncLogic = _ => Task.FromException(expected) }; - - // Act & Assert - var componentId = renderer.AssignRootComponentId(component); - var actual = await Assert.ThrowsAsync(() => renderer.RenderRootComponentAsync(componentId)); - - // Assert - Assert.Same(expected, actual); - } - - [Fact] - public async Task RenderRootComponentAsync_ReportsErrorDuringOnParameterSet() - { - // Arrange - var expected = new TimeZoneNotFoundException(); - var renderer = new TestRenderer(); - var component = new TestComponent { OnParametersSetLogic = _ => throw expected }; - - // Act & Assert - var componentId = renderer.AssignRootComponentId(component); - var actual = await Assert.ThrowsAsync(() => renderer.RenderRootComponentAsync(componentId)); - - // Assert - Assert.Same(expected, actual); - } - - [Fact] - public async Task RenderRootComponentAsync_ReportsErrorDuringOnParameterSetAsync() - { - // Arrange - var expected = new TimeZoneNotFoundException(); - var renderer = new TestRenderer(); - var component = new TestComponent { OnParametersSetAsyncLogic = _ => Task.FromException(expected) }; - - // Act & Assert - var componentId = renderer.AssignRootComponentId(component); - var actual = await Assert.ThrowsAsync(() => renderer.RenderRootComponentAsync(componentId)); - - // Assert - Assert.Same(expected, actual); - } - - private class TestComponent : ComponentBase - { - public bool RunsBaseOnInit { get; set; } = true; - - public bool RunsBaseOnInitAsync { get; set; } = true; - - public bool RunsBaseOnParametersSet { get; set; } = true; - - public bool RunsBaseOnParametersSetAsync { get; set; } = true; - - public bool RunsBaseOnAfterRender { get; set; } = true; - - public bool RunsBaseOnAfterRenderAsync { get; set; } = true; - - public Action OnInitLogic { get; set; } - - public Func OnInitAsyncLogic { get; set; } - - public Action OnParametersSetLogic { get; set; } - - public Func OnParametersSetAsyncLogic { get; set; } - - public Action OnAfterRenderLogic { get; set; } - - public Func OnAfterRenderAsyncLogic { get; set; } - - public int Counter { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenElement(0, "p"); - builder.AddContent(1, Counter); - builder.CloseElement(); - } - - protected override void OnInitialized() - { - if (RunsBaseOnInit) - { - base.OnInitialized(); - } - - OnInitLogic?.Invoke(this); - } - - protected override async Task OnInitializedAsync() - { - if (RunsBaseOnInitAsync) - { - await base.OnInitializedAsync(); - } - - if (OnInitAsyncLogic != null) - { - await OnInitAsyncLogic.Invoke(this); - } - } - - protected override void OnParametersSet() - { - if (RunsBaseOnParametersSet) - { - base.OnParametersSet(); - } - - OnParametersSetLogic?.Invoke(this); - } - - protected override async Task OnParametersSetAsync() - { - if (RunsBaseOnParametersSetAsync) - { - await base.OnParametersSetAsync(); - } - - if (OnParametersSetAsyncLogic != null) - { - await OnParametersSetAsyncLogic(this); - } - } - - protected override void OnAfterRender(bool firstRender) - { - if (RunsBaseOnAfterRender) - { - base.OnAfterRender(firstRender); - } - - if (OnAfterRenderLogic != null) - { - OnAfterRenderLogic(this, firstRender); - } - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (RunsBaseOnAfterRenderAsync) - { - await base.OnAfterRenderAsync(firstRender); - } - - if (OnAfterRenderAsyncLogic != null) - { - await OnAfterRenderAsyncLogic(this, firstRender); - } - } - } - } -} diff --git a/src/Components/Components/test/ComponentFactoryTest.cs b/src/Components/Components/test/ComponentFactoryTest.cs deleted file mode 100644 index 4dd4de56e0ad..000000000000 --- a/src/Components/Components/test/ComponentFactoryTest.cs +++ /dev/null @@ -1,168 +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.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class ComponentFactoryTest - { - [Fact] - public void InstantiateComponent_CreatesInstance() - { - // Arrange - var componentType = typeof(EmptyComponent); - var factory = new ComponentFactory(); - - // Act - var instance = factory.InstantiateComponent(GetServiceProvider(), componentType); - - // Assert - Assert.NotNull(instance); - Assert.IsType(instance); - } - - [Fact] - public void InstantiateComponent_AssignsPropertiesWithInjectAttribute() - { - // Arrange - var componentType = typeof(ComponentWithInjectProperties); - var factory = new ComponentFactory(); - - // Act - var instance = factory.InstantiateComponent(GetServiceProvider(), componentType); - - // Assert - Assert.NotNull(instance); - var component = Assert.IsType(instance); - // Public, and non-public properties, and properties with non-public setters should get assigned - Assert.NotNull(component.Property1); - Assert.NotNull(component.GetProperty2()); - Assert.NotNull(component.Property3); - Assert.NotNull(component.Property4); - } - - [Fact] - public void InstantiateComponent_AssignsPropertiesWithInjectAttributeOnBaseType() - { - // Arrange - var componentType = typeof(DerivedComponent); - var factory = new ComponentFactory(); - - // Act - var instance = factory.InstantiateComponent(GetServiceProvider(), componentType); - - // Assert - Assert.NotNull(instance); - var component = Assert.IsType(instance); - Assert.NotNull(component.Property1); - Assert.NotNull(component.GetProperty2()); - Assert.NotNull(component.Property3); - - // Property on derived type without [Inject] should not be assigned - Assert.Null(component.Property4); - // Property on the base type with the [Inject] attribute should - Assert.NotNull(((ComponentWithInjectProperties)component).Property4); - } - - [Fact] - public void InstantiateComponent_IgnoresPropertiesWithoutInjectAttribute() - { - // Arrange - var componentType = typeof(ComponentWithNonInjectableProperties); - var factory = new ComponentFactory(); - - // Act - var instance = factory.InstantiateComponent(GetServiceProvider(), componentType); - - // Assert - Assert.NotNull(instance); - var component = Assert.IsType(instance); - // Public, and non-public properties, and properties with non-public setters should get assigned - Assert.NotNull(component.Property1); - Assert.Null(component.Property2); - } - - private static IServiceProvider GetServiceProvider() - { - return new ServiceCollection() - .AddTransient() - .AddTransient() - .BuildServiceProvider(); - } - - private class EmptyComponent : IComponent - { - public void Attach(RenderHandle renderHandle) - { - throw new NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - - private class ComponentWithInjectProperties : IComponent - { - [Inject] - public TestService1 Property1 { get; set; } - - [Inject] - private TestService2 Property2 { get; set; } - - [Inject] - public TestService1 Property3 { get; private set; } - - [Inject] - public TestService1 Property4 { get; set; } - - public TestService2 GetProperty2() => Property2; - - public void Attach(RenderHandle renderHandle) - { - throw new NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - - private class ComponentWithNonInjectableProperties : IComponent - { - [Inject] - public TestService1 Property1 { get; set; } - - public TestService1 Property2 { get; set; } - - public void Attach(RenderHandle renderHandle) - { - throw new NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - - private class DerivedComponent : ComponentWithInjectProperties - { - public new TestService2 Property4 { get; set; } - - [Inject] - public TestService2 Property5 { get; set; } - } - - public class TestService1 { } - public class TestService2 { } - } -} diff --git a/src/Components/Components/test/DependencyInjectionTest.cs b/src/Components/Components/test/DependencyInjectionTest.cs deleted file mode 100644 index 2a77c753258c..000000000000 --- a/src/Components/Components/test/DependencyInjectionTest.cs +++ /dev/null @@ -1,204 +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; -using Microsoft.AspNetCore.Components.Test.Helpers; -using System; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class DependencyInjectionTest - { - private readonly TestRenderer _renderer; - private readonly TestServiceProvider _serviceProvider; - - public DependencyInjectionTest() - { - _serviceProvider = new TestServiceProvider(); - _renderer = new TestRenderer(_serviceProvider); - } - - [Fact] - public void IgnoresPropertiesWithoutInjectAttribute() - { - // Arrange/Act - var component = InstantiateComponent(); - - // Assert - Assert.Null(component.SomeProperty); - Assert.Null(component.PrivatePropertyValue); - } - - [Fact] - public void IgnoresStaticProperties() - { - // Arrange/Act - var component = InstantiateComponent(); - - // Assert - Assert.Null(HasStaticProperties.StaticPropertyWithInject); - Assert.Null(HasStaticProperties.StaticPropertyWithoutInject); - } - - [Fact] - public void ThrowsForInjectablePropertiesWithoutSetter() - { - var ex = Assert.Throws(() => - { - InstantiateComponent(); - }); - - Assert.Equal($"Cannot provide a value for property '{nameof(HasInjectableProperty.MyService)}' " + - $"on type '{typeof(HasGetOnlyPropertyWithInject).FullName}' because the property " + - $"has no setter.", ex.Message); - } - - [Fact] - public void ThrowsIfNoSuchServiceIsRegistered() - { - var ex = Assert.Throws(() => - { - InstantiateComponent(); - }); - - Assert.Equal($"Cannot provide a value for property '{nameof(HasInjectableProperty.MyService)}' " + - $"on type '{typeof(HasInjectableProperty).FullName}'. There is no registered service " + - $"of type '{typeof(IMyService).FullName}'.", ex.Message); - } - - [Fact] - public void SetsInjectablePropertyValueIfServiceIsRegistered() - { - // Arrange - var serviceInstance = new MyServiceImplementation(); - _serviceProvider.AddService(serviceInstance); - - // Act - var instance = InstantiateComponent(); - - // Assert - Assert.Same(serviceInstance, instance.MyService); - } - - [Fact] - public void HandlesInjectablePropertyScenarios() - { - // Arrange - var serviceInstance = new MyServiceImplementation(); - var otherServiceInstance = new MyOtherServiceImplementation(); - var concreteServiceInstance = new MyConcreteService(); - _serviceProvider.AddService(serviceInstance); - _serviceProvider.AddService(otherServiceInstance); - _serviceProvider.AddService(concreteServiceInstance); - - // Act - var instance = InstantiateComponent(); - - // Assert - Assert.Same(serviceInstance, instance.PublicReadWrite); - Assert.Same(serviceInstance, instance.PublicReadOnly); - Assert.Same(serviceInstance, instance.PrivateValue); - Assert.Same(otherServiceInstance, instance.DifferentServiceType); - Assert.Same(concreteServiceInstance, instance.ConcreteServiceType); - } - - [Fact] - public void SetsInheritedInjectableProperties() - { - // Arrange - var serviceInstance = new MyServiceImplementation(); - _serviceProvider.AddService(serviceInstance); - - // Act - var instance = InstantiateComponent(); - - // Assert - Assert.Same(serviceInstance, instance.MyService); - } - - [Fact] - public void SetsPrivateInheritedInjectableProperties() - { - // Arrange - var serviceInstance = new MyServiceImplementation(); - _serviceProvider.AddService(serviceInstance); - - // Act - var instance = InstantiateComponent(); - - // Assert - Assert.Same(serviceInstance, instance.PrivateMyService); - } - - private T InstantiateComponent() where T: IComponent - => _renderer.InstantiateComponent(); - - class HasPropertiesWithoutInjectAttribute : TestComponent - { - public IMyService SomeProperty { get; set; } - public IMyService PrivatePropertyValue => PrivateProperty; - private IMyService PrivateProperty { get; set; } - } - - class HasStaticProperties : TestComponent - { - [Inject] public static IMyService StaticPropertyWithInject { get; set; } - public static IMyService StaticPropertyWithoutInject { get; set; } - } - - class HasGetOnlyPropertyWithInject : TestComponent - { - [Inject] public IMyService MyService { get; } - } - - class HasInjectableProperty : TestComponent - { - [Inject] public IMyService MyService { get; set; } - } - - class HasPrivateInjectableProperty : TestComponent - { - [Inject] private IMyService MyService { get; set; } - - public IMyService PrivateMyService => MyService; - } - - class HasInheritedPrivateInjectableProperty : HasPrivateInjectableProperty { } - - class HasManyInjectableProperties : TestComponent - { - [Inject] public IMyService PublicReadWrite { get; set; } - [Inject] public IMyService PublicReadOnly { get; private set; } - [Inject] private IMyService Private { get; set; } - [Inject] public IMyOtherService DifferentServiceType { get; set; } - [Inject] public MyConcreteService ConcreteServiceType { get; set; } - - public IMyService PrivateValue => Private; - } - - class HasInheritedInjectedProperty : HasInjectableProperty { } - - interface IMyService { } - interface IMyOtherService { } - - class MyServiceImplementation : IMyService { } - class MyOtherServiceImplementation : IMyOtherService { } - class MyConcreteService { } - - class TestComponent : IComponent - { - // IMPORTANT: The fact that these throw demonstrates that the injection - // happens before any of the lifecycle methods. If you change these to - // not throw, then be sure also to add a test to verify that injection - // occurs before lifecycle methods. - - public void Attach(RenderHandle renderHandle) - => throw new NotImplementedException(); - - public Task SetParametersAsync(ParameterView parameters) - => throw new NotImplementedException(); - } - } -} diff --git a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs b/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs deleted file mode 100644 index 8df50921127b..000000000000 --- a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs +++ /dev/null @@ -1,713 +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.ComponentModel; -using System.Globalization; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class EventCallbackFactoryBinderExtensionsTest - { - [Fact] - public async Task CreateBinder_SwallowsConversionException() - { - // Arrange - var value = 17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "not-an-integer!", }); - - Assert.Equal(17, value); // Setter not called - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_IfConverterThrows_ConvertsEmptyStringToDefault() - { - // Arrange - var value = 17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = string.Empty, }); - - Assert.Equal(0, value); // Calls setter to apply default value for this type - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_ThrowsSetterException() - { - // Arrange - var component = new EventCountingComponent(); - Action setter = (_) => { throw new InvalidTimeZoneException(); }; - - var binder = EventCallback.Factory.CreateBinder(component, setter, 17); - - // Act - await Assert.ThrowsAsync(() => - { - return binder.InvokeAsync(new ChangeEventArgs() { Value = "18", }); - }); - - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_BindsEmpty_DoesNotCallSetter() - { - // Arrange - var value = 17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "not-an-integer!", }); - - Assert.Equal(17, value); // Setter not called - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_BindsEmpty_CallsSetterForNullable() - { - // Arrange - var value = (int?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "", }); - - Assert.Null(value); // Setter called - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_String() - { - // Arrange - var value = "hi"; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = "bye"; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue, }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Bool() - { - // Arrange - var value = false; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = true; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = true, }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableBool() - { - // Arrange - var value = (bool?)false; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (bool?)true; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = true, }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Int() - { - // Arrange - var value = 17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = 42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableInt() - { - // Arrange - var value = (int?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (int?)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Long() - { - // Arrange - var value = (long)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (long)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableLong() - { - // Arrange - var value = (long?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (long?)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Float() - { - // Arrange - var value = (float)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (float)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableFloat() - { - // Arrange - var value = (float?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (float?)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Double() - { - // Arrange - var value = (double)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (double)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDouble() - { - // Arrange - var value = (double?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (double?)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Decimal() - { - // Arrange - var value = (decimal)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (decimal)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDecimal() - { - // Arrange - var value = (decimal?)17; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = (decimal?)42; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_Enum() - { - // Arrange - var value = AttributeTargets.All; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = AttributeTargets.Class; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableEnum() - { - // Arrange - var value = (AttributeTargets?)AttributeTargets.All; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = AttributeTargets.Class; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_DateTime() - { - // Arrange - var value = DateTime.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDateTime() - { - // Arrange - var value = (DateTime?)DateTime.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_DateTime_Format() - { - // Arrange - var value = DateTime.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - var format = "ddd yyyy-MM-dd"; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, format); - - var expectedValue = new DateTime(2018, 3, 4); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDateTime_Format() - { - // Arrange - var value = (DateTime?)DateTime.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - var format = "ddd yyyy-MM-dd"; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, format); - - var expectedValue = new DateTime(2018, 3, 4); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_DateTimeOffset() - { - // Arrange - var value = DateTimeOffset.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDateTimeOffset() - { - // Arrange - var value = (DateTimeOffset?)DateTimeOffset.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_DateTimeOffset_Format() - { - // Arrange - var value = DateTimeOffset.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - var format = "ddd yyyy-MM-dd"; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, format); - - var expectedValue = new DateTime(2018, 3, 4); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NullableDateTimeOffset_Format() - { - // Arrange - var value = (DateTimeOffset?)DateTimeOffset.Now; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - var format = "ddd yyyy-MM-dd"; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, format); - - var expectedValue = new DateTime(2018, 3, 4); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - // This uses a type converter - [Fact] - public async Task CreateBinder_Guid() - { - // Arrange - var value = Guid.NewGuid(); - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = Guid.NewGuid(); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - // This uses a type converter - [Fact] - public async Task CreateBinder_NullableGuid() - { - // Arrange - var value = (Guid?)Guid.NewGuid(); - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = Guid.NewGuid(); - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_CustomTypeConverter() - { - // Arrange - var value = new SecretMessage() { Message = "A message", }; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value); - - var expectedValue = new SecretMessage() { Message = "TypeConverter may be old, but it still works!", }; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); - - Assert.Equal(expectedValue.Message, value.Message); - Assert.Equal(1, component.Count); - } - - [Fact] - public void CreateBinder_GenericWithoutTypeConverter_Throws() - { - var value = new ClassWithoutTypeConverter(); - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var ex = Assert.Throws(() => EventCallback.Factory.CreateBinder(component, setter, value)); - - Assert.Equal( - $"The type '{typeof(ClassWithoutTypeConverter).FullName}' does not have an associated TypeConverter that supports conversion from a string. " + - $"Apply 'TypeConverterAttribute' to the type to register a converter.", - ex.Message); - } - - [Fact] - [ReplaceCulture("fr-FR", "fr-FR")] - public async Task CreateBinder_NumericType_WithCurrentCulture() - { - // Arrange - var value = 17_000; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, culture: null); - - var expectedValue = 42_000; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42 000,00", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task CreateBinder_NumericType_WithInvariantCulture() - { - // Arrange - var value = 17_000; - var component = new EventCountingComponent(); - Action setter = (_) => value = _; - - var binder = EventCallback.Factory.CreateBinder(component, setter, value, CultureInfo.InvariantCulture); - - var expectedValue = 42_000; - - // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = "42,000.00", }); - - Assert.Equal(expectedValue, value); - Assert.Equal(1, component.Count); - } - - private class EventCountingComponent : IComponent, IHandleEvent - { - public int Count; - - public Task HandleEventAsync(EventCallbackWorkItem item, object arg) - { - Count++; - return item.InvokeAsync(arg); - } - - public void Attach(RenderHandle renderHandle) - { - throw new System.NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new System.NotImplementedException(); - } - } - - private class ClassWithoutTypeConverter - { - } - - [TypeConverter(typeof(SecretMessageTypeConverter))] - private class SecretMessage - { - public string Message { get; set; } - - public override string ToString() - { - return Message; - } - } - - private class SecretMessageTypeConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - - return false; - } - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string message) - { - return new SecretMessage() { Message = message, }; - } - - return null; - } - } - } -} diff --git a/src/Components/Components/test/EventCallbackFactoryTest.cs b/src/Components/Components/test/EventCallbackFactoryTest.cs deleted file mode 100644 index 69b7bfa7480b..000000000000 --- a/src/Components/Components/test/EventCallbackFactoryTest.cs +++ /dev/null @@ -1,654 +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.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class EventCallbackFactoryTest - { - [Fact] - public void Create_EventCallback_ReturnsInput() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - var input = new EventCallback(component, @delegate); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, input); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_Action_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_Action_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_Action_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)(() => { }); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_Action_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Action)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_ActionT_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeActionOfT; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_ActionT_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeActionOfT; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_ActionT_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)((s) => { }); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_ActionT_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Action)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTask_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTask; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTask_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTask; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTask_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)(() => Task.CompletedTask); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTTask_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTTask; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTask_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Func)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTTask_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTTask; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTTask_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)((s) => Task.CompletedTask); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void Create_FuncTTask_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Func)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_EventCallback_ReturnsInput() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - var input = new EventCallback(component, @delegate); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, input); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_Action_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_Action_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeAction; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_Action_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)(() => { }); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_Action_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Action)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_ActionT_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeActionOfT; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_ActionT_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)component.SomeActionOfT; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_ActionT_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Action)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_ActionT_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)((s) => { }); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTask_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTask; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTask_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTask; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTask_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)(() => Task.CompletedTask); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTask_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Func)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTTask_AlreadyBoundToReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTTask; - - // Act - var callback = EventCallback.Factory.Create(component, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTTask_DifferentReceiver() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)component.SomeFuncTTask; - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.False(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTTask_Unbound() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)((s) => Task.CompletedTask); - - var anotherComponent = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(anotherComponent, @delegate); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(anotherComponent, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateT_FuncTTask_Null() - { - // Arrange - var component = new EventComponent(); - - // Act - var callback = EventCallback.Factory.Create(component, (Func)null); - - // Assert - Assert.Null(callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateInferred_ActionT() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Action)((s) => { }); - - // Act - var callback = EventCallback.Factory.CreateInferred(component, @delegate, "hi"); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - [Fact] - public void CreateInferred_FuncTTask() - { - // Arrange - var component = new EventComponent(); - var @delegate = (Func)((s) => Task.CompletedTask); - - // Act - var callback = EventCallback.Factory.CreateInferred(component, @delegate, "hi"); - - // Assert - Assert.Same(@delegate, callback.Delegate); - Assert.Same(component, callback.Receiver); - Assert.True(callback.RequiresExplicitReceiver); - } - - private class EventComponent : IComponent, IHandleEvent - { - public void SomeAction() - { - } - - public void SomeActionOfT(string e) - { - } - - public Task SomeFuncTask() - { - return Task.CompletedTask; - } - - public Task SomeFuncTTask(string s) - { - return Task.CompletedTask; - } - - public void Attach(RenderHandle renderHandle) - { - throw new NotImplementedException(); - } - - public Task HandleEventAsync(EventCallbackWorkItem item, object arg) - { - throw new NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - } -} diff --git a/src/Components/Components/test/EventCallbackTest.cs b/src/Components/Components/test/EventCallbackTest.cs deleted file mode 100644 index 25405c218088..000000000000 --- a/src/Components/Components/test/EventCallbackTest.cs +++ /dev/null @@ -1,457 +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.Text; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class EventCallbackTest - { - [Fact] - public async Task EventCallback_Default() - { - // Arrange - var callback = default(EventCallback); - - // Act & Assert (Does not throw) - await callback.InvokeAsync(null); - } - - [Fact] - public async Task EventCallbackOfT_Default() - { - // Arrange - var callback = default(EventCallback); - - // Act & Assert (Does not throw) - await callback.InvokeAsync(null); - } - - - [Fact] - public async Task EventCallback_NullReceiver() - { - // Arrange - int runCount = 0; - var callback = new EventCallback(null, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - } - - [Fact] - public async Task EventCallbackOfT_NullReceiver() - { - // Arrange - int runCount = 0; - var callback = new EventCallback(null, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - } - - [Fact] - public async Task EventCallback_Action_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_Action_IgnoresArg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_ActionT_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Null(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_ActionT_Arg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.NotNull(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_ActionT_Arg_ValueType() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - int arg = -1; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act - await callback.InvokeAsync(17); - - - // Assert - Assert.Equal(17, arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_ActionT_ArgMismatch() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act & Assert - await Assert.ThrowsAsync(() => - { - return callback.InvokeAsync(new StringBuilder()); - }); - } - - [Fact] - public async Task EventCallback_FuncTask_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_FuncTask_IgnoresArg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_FuncTTask_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Null(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_FuncTTask_Arg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.NotNull(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_FuncTTask_Arg_ValueType() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - int arg = -1; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(17); - - - // Assert - Assert.Equal(17, arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallback_FuncTTask_ArgMismatch() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act & Assert - await Assert.ThrowsAsync(() => - { - return callback.InvokeAsync(new StringBuilder()); - }); - } - - [Fact] - public async Task EventCallbackOfT_Action_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_Action_IgnoresArg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_ActionT_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Null(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_ActionT_Arg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.NotNull(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_FuncTask_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_FuncTask_IgnoresArg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_FuncTTask_Null() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(null); - - - // Assert - Assert.Null(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - [Fact] - public async Task EventCallbackOfT_FuncTTask_Arg() - { - // Arrange - var component = new EventCountingComponent(); - - int runCount = 0; - EventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); - - // Act - await callback.InvokeAsync(new EventArgs()); - - - // Assert - Assert.NotNull(arg); - Assert.Equal(1, runCount); - Assert.Equal(1, component.Count); - } - - private class EventCountingComponent : IComponent, IHandleEvent - { - public int Count; - - public Task HandleEventAsync(EventCallbackWorkItem item, object arg) - { - Count++; - return item.InvokeAsync(arg); - } - - public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - - public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); - } - } -} diff --git a/src/Components/Components/test/LayoutViewTest.cs b/src/Components/Components/test/LayoutViewTest.cs deleted file mode 100644 index 592cb7e62d15..000000000000 --- a/src/Components/Components/test/LayoutViewTest.cs +++ /dev/null @@ -1,326 +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.Linq; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class LayoutViewTest - { - private readonly TestRenderer _renderer; - private readonly LayoutView _layoutViewComponent; - private readonly int _layoutViewComponentId; - - public LayoutViewTest() - { - _renderer = new TestRenderer(); - _layoutViewComponent = new LayoutView(); - _layoutViewComponentId = _renderer.AssignRootComponentId(_layoutViewComponent); - } - - [Fact] - public void GivenNoParameters_RendersNothing() - { - // Arrange/Act - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.Empty)); - Assert.True(setParametersTask.IsCompletedSuccessfully); - var frames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable(); - - // Assert - Assert.Single(_renderer.Batches); - Assert.Empty(frames); - } - - [Fact] - public void GivenContentButNoLayout_RendersContent() - { - // Arrange/Act - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(123, "Hello"); - builder.AddContent(456, "Goodbye"); - })} - }))); - Assert.True(setParametersTask.IsCompletedSuccessfully); - var frames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable(); - - // Assert - Assert.Single(_renderer.Batches); - Assert.Collection(frames, - frame => AssertFrame.Text(frame, "Hello", 123), - frame => AssertFrame.Text(frame, "Goodbye", 456)); - } - - [Fact] - public void GivenLayoutButNoContent_RendersLayoutWithEmptyBody() - { - // Arrange/Act - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(RootLayout) } - }))); - - // Assert - Assert.True(setParametersTask.IsCompletedSuccessfully); - var batch = _renderer.Batches.Single(); - - var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable(); - Assert.Collection(layoutViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 2, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1)); - - var rootLayoutComponentId = batch.GetComponentFrames().Single().ComponentId; - var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable(); - Assert.Collection(rootLayoutFrames, - frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0), - frame => AssertFrame.Region(frame, subtreeLength: 1), // i.e., empty region - frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2)); - } - - [Fact] - public void RendersContentInsideLayout() - { - // Arrange/Act - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(RootLayout) }, - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(123, "Hello"); - builder.AddContent(456, "Goodbye"); - })} - }))); - - // Assert - Assert.True(setParametersTask.IsCompletedSuccessfully); - var batch = _renderer.Batches.Single(); - - var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable(); - Assert.Collection(layoutViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 2, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1)); - - var rootLayoutComponentId = batch.GetComponentFrames().Single().ComponentId; - var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable(); - Assert.Collection(rootLayoutFrames, - frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0), - frame => AssertFrame.Region(frame, subtreeLength: 3), - frame => AssertFrame.Text(frame, "Hello", sequence: 123), - frame => AssertFrame.Text(frame, "Goodbye", sequence: 456), - frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2)); - } - - [Fact] - public void RendersContentInsideNestedLayout() - { - // Arrange/Act - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(NestedLayout) }, - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(123, "Hello"); - builder.AddContent(456, "Goodbye"); - })} - }))); - - // Assert - Assert.True(setParametersTask.IsCompletedSuccessfully); - var batch = _renderer.Batches.Single(); - - var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable(); - Assert.Collection(layoutViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 2, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1)); - - var rootLayoutComponentId = batch.GetComponentFrames().Single().ComponentId; - var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable(); - Assert.Collection(rootLayoutFrames, - frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0), - frame => AssertFrame.Region(frame, subtreeLength: 3, sequence: 1), - frame => AssertFrame.Component(frame, subtreeLength: 2, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1), - frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2)); - - var nestedLayoutComponentId = batch.GetComponentFrames().Single().ComponentId; - var nestedLayoutFrames = _renderer.GetCurrentRenderTreeFrames(nestedLayoutComponentId).AsEnumerable(); - Assert.Collection(nestedLayoutFrames, - frame => AssertFrame.Text(frame, "NestedLayout starts here", sequence: 0), - frame => AssertFrame.Region(frame, subtreeLength: 3, sequence: 1), - frame => AssertFrame.Text(frame, "Hello", sequence: 123), - frame => AssertFrame.Text(frame, "Goodbye", sequence: 456), - frame => AssertFrame.Text(frame, "NestedLayout ends here", sequence: 2)); - } - - [Fact] - public void CanChangeContentWithSameLayout() - { - // Arrange - var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(NestedLayout) }, - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(0, "Initial content"); - })} - }))); - - // Act - Assert.True(setParametersTask.IsCompletedSuccessfully); - _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(NestedLayout) }, - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(0, "Changed content"); - })} - }))); - - // Assert - Assert.Equal(2, _renderer.Batches.Count); - var batch = _renderer.Batches[1]; - Assert.Equal(0, batch.DisposedComponentIDs.Count); - Assert.Collection(batch.DiffsInOrder, - diff => Assert.Empty(diff.Edits), // LayoutView rerendered, but with no changes - diff => Assert.Empty(diff.Edits), // RootLayout rerendered, but with no changes - diff => - { - // NestedLayout rerendered, patching content in place - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Changed content", - sequence: 0); - }); - }); - } - - [Fact] - public void CanChangeLayout() - { - // Arrange - var setParametersTask1 = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(NestedLayout) }, - { nameof(LayoutView.ChildContent), (RenderFragment)(builder => { - builder.AddContent(0, "Some content"); - })} - }))); - Assert.True(setParametersTask1.IsCompletedSuccessfully); - - // Act - var setParametersTask2 = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(LayoutView.Layout), typeof(OtherNestedLayout) }, - }))); - - // Assert - Assert.True(setParametersTask2.IsCompletedSuccessfully); - Assert.Equal(2, _renderer.Batches.Count); - var batch = _renderer.Batches[1]; - Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposes NestedLayout - Assert.Collection(batch.DiffsInOrder, - diff => Assert.Empty(diff.Edits), // LayoutView rerendered, but with no changes - diff => - { - // RootLayout rerendered, changing child - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - }, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - AssertFrame.Component( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - sequence: 0); - }); - }, - diff => - { - // Inserts new OtherNestedLayout - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(0, edit.SiblingIndex); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "OtherNestedLayout starts here"); - }, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Some content"); - }, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(2, edit.SiblingIndex); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "OtherNestedLayout ends here"); - }); - }); - } - - private class RootLayout : AutoRenderComponent - { - [Parameter] - public RenderFragment Body { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - if (Body == null) - { - // Prove that we don't expect layouts to tolerate null values for Body - throw new InvalidOperationException("Got a null body when not expecting it"); - } - - builder.AddContent(0, "RootLayout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "RootLayout ends here"); - } - } - - [Layout(typeof(RootLayout))] - private class NestedLayout : AutoRenderComponent - { - [Parameter] - public RenderFragment Body { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "NestedLayout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "NestedLayout ends here"); - } - } - - [Layout(typeof(RootLayout))] - private class OtherNestedLayout : AutoRenderComponent - { - [Parameter] - public RenderFragment Body { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "OtherNestedLayout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "OtherNestedLayout ends here"); - } - } - } -} diff --git a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj b/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj deleted file mode 100644 index fd2a5406c165..000000000000 --- a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - Microsoft.AspNetCore.Components - - - - - - - - - - - - - diff --git a/src/Components/Components/test/NavigationManagerTest.cs b/src/Components/Components/test/NavigationManagerTest.cs deleted file mode 100644 index 9b857bb04477..000000000000 --- a/src/Components/Components/test/NavigationManagerTest.cs +++ /dev/null @@ -1,117 +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 Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class NavigationManagerTest - { - [Theory] - [InlineData("scheme://host/", "scheme://host/")] - [InlineData("scheme://host:123/", "scheme://host:123/")] - [InlineData("scheme://host/path", "scheme://host/")] - [InlineData("scheme://host/path/", "scheme://host/path/")] - [InlineData("scheme://host/path/page?query=string&another=here", "scheme://host/path/")] - public void ComputesCorrectBaseUri(string baseUri, string expectedResult) - { - var actualResult = NavigationManager.NormalizeBaseUri(baseUri); - Assert.Equal(expectedResult, actualResult); - } - - [Theory] - [InlineData("scheme://host/", "scheme://host", "")] - [InlineData("scheme://host/", "scheme://host/", "")] - [InlineData("scheme://host/", "scheme://host/path", "path")] - [InlineData("scheme://host/path/", "scheme://host/path/", "")] - [InlineData("scheme://host/path/", "scheme://host/path/more", "more")] - [InlineData("scheme://host/path/", "scheme://host/path", "")] - [InlineData("scheme://host/path/", "scheme://host/path#hash", "#hash")] - [InlineData("scheme://host/path/", "scheme://host/path/#hash", "#hash")] - [InlineData("scheme://host/path/", "scheme://host/path/more#hash", "more#hash")] - public void ComputesCorrectValidBaseRelativePaths(string baseUri, string uri, string expectedResult) - { - var navigationManager = new TestNavigationManager(baseUri); - - var actualResult = navigationManager.ToBaseRelativePath(uri); - Assert.Equal(expectedResult, actualResult); - } - - [Theory] - [InlineData("scheme://host/", "otherscheme://host/")] - [InlineData("scheme://host/", "scheme://otherhost/")] - [InlineData("scheme://host/path/", "scheme://host/")] - public void Initialize_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri) - { - var navigationManager = new TestNavigationManager(); - - var ex = Assert.Throws(() => - { - navigationManager.Initialize(baseUri, absoluteUri); - }); - - Assert.Equal( - $"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.", - ex.Message); - } - - [Theory] - [InlineData("scheme://host/", "otherscheme://host/")] - [InlineData("scheme://host/", "scheme://otherhost/")] - [InlineData("scheme://host/path/", "scheme://host/")] - public void Uri_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri) - { - var navigationManager = new TestNavigationManager(baseUri); - - var ex = Assert.Throws(() => - { - navigationManager.ToBaseRelativePath(absoluteUri); - }); - - Assert.Equal( - $"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.", - ex.Message); - } - - [Theory] - [InlineData("scheme://host/", "otherscheme://host/")] - [InlineData("scheme://host/", "scheme://otherhost/")] - [InlineData("scheme://host/path/", "scheme://host/")] - public void ToBaseRelativePath_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri) - { - var navigationManager = new TestNavigationManager(baseUri); - - var ex = Assert.Throws(() => - { - navigationManager.ToBaseRelativePath(absoluteUri); - }); - - Assert.Equal( - $"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.", - ex.Message); - } - - private class TestNavigationManager : NavigationManager - { - public TestNavigationManager() - { - } - - public TestNavigationManager(string baseUri = null, string uri = null) - { - Initialize(baseUri ?? "http://example.com/", uri ?? baseUri ?? "http://example.com/welcome-page"); - } - - public new void Initialize(string baseUri, string uri) - { - base.Initialize(baseUri, uri); - } - - protected override void NavigateToCore(string uri, bool forceLoad) - { - throw new System.NotImplementedException(); - } - } - } -} diff --git a/src/Components/Components/test/OwningComponentBaseTest.cs b/src/Components/Components/test/OwningComponentBaseTest.cs deleted file mode 100644 index 155231b40bb4..000000000000 --- a/src/Components/Components/test/OwningComponentBaseTest.cs +++ /dev/null @@ -1,61 +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.Dynamic; -using System.Linq; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public class OwningComponentBaseTest - { - [Fact] - public void CreatesScopeAndService() - { - var services = new ServiceCollection(); - services.AddSingleton(); - services.AddTransient(); - var serviceProvider = services.BuildServiceProvider(); - - var counter = serviceProvider.GetRequiredService(); - var renderer = new TestRenderer(serviceProvider); - var component1 = renderer.InstantiateComponent(); - - Assert.NotNull(component1.MyService); - Assert.Equal(1, counter.CreatedCount); - Assert.Equal(0, counter.DisposedCount); - - ((IDisposable)component1).Dispose(); - Assert.Equal(1, counter.CreatedCount); - Assert.Equal(1, counter.DisposedCount); - } - - private class Counter - { - public int CreatedCount { get; set; } - public int DisposedCount { get; set; } - } - - private class MyService : IDisposable - { - public MyService(Counter counter) - { - Counter = counter; - Counter.CreatedCount++; - } - - public Counter Counter { get; } - - void IDisposable.Dispose() => Counter.DisposedCount++; - } - - private class MyOwningComponent : OwningComponentBase - { - public MyService MyService => Service; - } - } -} diff --git a/src/Components/Components/test/ParameterViewTest.Assignment.cs b/src/Components/Components/test/ParameterViewTest.Assignment.cs deleted file mode 100644 index 9df9feab9ff6..000000000000 --- a/src/Components/Components/test/ParameterViewTest.Assignment.cs +++ /dev/null @@ -1,718 +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; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Components.Rendering; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public partial class ParameterViewTest - { - [Fact] - public void IncomingParameterMatchesAnnotatedPrivateProperty_SetsValue() - { - // Arrange - var someObject = new object(); - var parameters = new ParameterViewBuilder - { - { nameof(HasInstanceProperties.IntProp), 123 }, - { nameof(HasInstanceProperties.StringProp), "Hello" }, - { HasInstanceProperties.ObjectPropName, someObject }, - }.Build(); - var target = new HasInstanceProperties(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(123, target.IntProp); - Assert.Equal("Hello", target.StringProp); - Assert.Same(someObject, target.ObjectPropCurrentValue); - } - - [Fact] - public void IncomingParameterMatchesDeclaredParameterCaseInsensitively_SetsValue() - { - // Arrange - var parameters = new ParameterViewBuilder - { - { nameof(HasInstanceProperties.IntProp).ToLowerInvariant(), 123 } - }.Build(); - var target = new HasInstanceProperties(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(123, target.IntProp); - } - - [Fact] - public void IncomingParameterMatchesInheritedDeclaredParameter_SetsValue() - { - // Arrange - var parameters = new ParameterViewBuilder - { - { nameof(HasInheritedProperties.IntProp), 123 }, - { nameof(HasInheritedProperties.DerivedClassIntProp), 456 }, - }.Build(); - var target = new HasInheritedProperties(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(123, target.IntProp); - Assert.Equal(456, target.DerivedClassIntProp); - } - - [Fact] - public void IncomingParameterMatchesOverridenParameter_ThatDoesNotHasAttribute() - { - // Test for https://github.com/aspnet/AspNetCore/issues/13162 - // Arrange - var parameters = new ParameterViewBuilder - { - { nameof(DerivedType.VirtualProp), 123 }, - }.Build(); - var target = new DerivedType(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(123, target.VirtualProp); - } - - [Fact] - public void NoIncomingParameterMatchesDeclaredParameter_LeavesValueUnchanged() - { - // Arrange - var existingObjectValue = new object(); - var target = new HasInstanceProperties - { - IntProp = 456, - StringProp = "Existing value", - ObjectPropCurrentValue = existingObjectValue - }; - - var parameters = new ParameterViewBuilder().Build(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(456, target.IntProp); - Assert.Equal("Existing value", target.StringProp); - Assert.Same(existingObjectValue, target.ObjectPropCurrentValue); - } - - [Fact] - public void IncomingCascadingValueMatchesCascadingParameter_SetsValue() - { - // Arrange - var builder = new ParameterViewBuilder(); - builder.Add(nameof(HasCascadingParameter.Cascading), "hi", cascading: true); - var parameters = builder.Build(); - - var target = new HasCascadingParameter(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal("hi", target.Cascading); - } - - [Fact] - public void NoIncomingCascadingValueMatchesDeclaredCascadingParameter_LeavesValueUnchanged() - { - // Arrange - var builder = new ParameterViewBuilder(); - var parameters = builder.Build(); - - var target = new HasCascadingParameter() - { - Cascading = "bye", - }; - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal("bye", target.Cascading); - } - - [Fact] - public void IncomingCascadingValueMatchesNoDeclaredParameter_Throws() - { - // Arrange - var builder = new ParameterViewBuilder(); - builder.Add("SomethingElse", "hi", cascading: true); - var parameters = builder.Build(); - - var target = new HasCascadingParameter(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"Object of type '{typeof(HasCascadingParameter).FullName}' does not have a property " + - $"matching the name 'SomethingElse'.", - ex.Message); - } - - [Fact] - public void IncomingParameterMatchesPropertyNotDeclaredAsParameter_Throws() - { - // Arrange - var target = new HasPropertyWithoutParameterAttribute(); - var parameters = new ParameterViewBuilder - { - { nameof(HasPropertyWithoutParameterAttribute.IntProp), 123 }, - }.Build(); - - // Act - var ex = Assert.Throws( - () => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal(default, target.IntProp); - Assert.Equal( - $"Object of type '{typeof(HasPropertyWithoutParameterAttribute).FullName}' has a property matching the name '{nameof(HasPropertyWithoutParameterAttribute.IntProp)}', " + - $"but it does not have [{nameof(ParameterAttribute)}] or [{nameof(CascadingParameterAttribute)}] applied.", - ex.Message); - } - - [Fact] - public void IncomingParameterMatchesPropertyNotPublic_Throws() - { - // Arrange - var target = new HasNonPublicPropertyWithParameterAttribute(); - var parameters = new ParameterViewBuilder - { - { nameof(HasNonPublicPropertyWithParameterAttribute.IntProp), 123 }, - }.Build(); - - // Act - var ex = Assert.Throws( - () => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal(default, target.IntProp); - Assert.Equal( - $"The type '{typeof(HasNonPublicPropertyWithParameterAttribute).FullName}' declares a parameter matching the name '{nameof(HasNonPublicPropertyWithParameterAttribute.IntProp)}' that is not public. Parameters must be public.", - ex.Message); - } - - [Fact] - public void IncomingCascadingParameterMatchesPropertyNotPublic_Works() - { - // Arrange - var target = new HasNonPublicCascadingParameter(); - var builder = new ParameterViewBuilder(); - builder.Add("Cascading", "Test", cascading: true); - var parameters = builder.Build(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal("Test", target.GetCascadingValue()); - } - - [Fact] - public void IncomingNonCascadingValueMatchesCascadingParameter_Throws() - { - // Arrange - var target = new HasCascadingParameter(); - var parameters = new ParameterViewBuilder - { - { nameof(HasCascadingParameter.Cascading), 123 }, - }.Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"Object of type '{typeof(HasCascadingParameter).FullName}' has a property matching the name '{nameof(HasCascadingParameter.Cascading)}', " + - $"but it does not have [{nameof(ParameterAttribute)}] applied.", - ex.Message); - } - - [Fact] - public void IncomingCascadingValueMatchesNonCascadingParameter_Throws() - { - // Arrange - var target = new HasInstanceProperties(); - var builder = new ParameterViewBuilder(); - builder.Add(nameof(HasInstanceProperties.IntProp), 16, cascading: true); - var parameters = builder.Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The property '{nameof(HasInstanceProperties.IntProp)}' on component type '{typeof(HasInstanceProperties).FullName}' " + - $"cannot be set using a cascading value.", - ex.Message); - } - - [Fact] - public void SettingCaptureUnmatchedValuesParameterExplicitlyWorks() - { - // Arrange - var target = new HasCaptureUnmatchedValuesProperty(); - var value = new Dictionary(); - var parameters = new ParameterViewBuilder - { - { nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues), value }, - }.Build(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Same(value, target.CaptureUnmatchedValues); - } - - [Fact] - public void SettingCaptureUnmatchedValuesParameterWithUnmatchedValuesWorks() - { - // Arrange - var target = new HasCaptureUnmatchedValuesProperty(); - var parameters = new ParameterViewBuilder - { - { nameof(HasCaptureUnmatchedValuesProperty.StringProp), "hi" }, - { "test1", 123 }, - { "test2", 456 }, - }.Build(); - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal("hi", target.StringProp); - Assert.Collection( - target.CaptureUnmatchedValues.OrderBy(kvp => kvp.Key), - kvp => - { - Assert.Equal("test1", kvp.Key); - Assert.Equal(123, kvp.Value); - }, - kvp => - { - Assert.Equal("test2", kvp.Key); - Assert.Equal(456, kvp.Value); - }); - } - - [Fact] - public void SettingCaptureUnmatchedValuesParameterExplicitlyAndImplicitly_Throws() - { - // Arrange - var target = new HasCaptureUnmatchedValuesProperty(); - var parameters = new ParameterViewBuilder - { - { nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues), new Dictionary() }, - { "test1", 123 }, - { "test2", 456 }, - }.Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The property '{nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues)}' on component type '{typeof(HasCaptureUnmatchedValuesProperty).FullName}' cannot be set explicitly when " + - $"also used to capture unmatched values. Unmatched values:" + Environment.NewLine + - $"test1" + Environment.NewLine + - $"test2", - ex.Message); - } - - [Fact] - public void SettingCaptureUnmatchedValuesParameterExplicitlyAndImplicitly_ReverseOrder_Throws() - { - // Arrange - var target = new HasCaptureUnmatchedValuesProperty(); - var parameters = new ParameterViewBuilder - { - { "test2", 456 }, - { "test1", 123 }, - { nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues), new Dictionary() }, - }.Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The property '{nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues)}' on component type '{typeof(HasCaptureUnmatchedValuesProperty).FullName}' cannot be set explicitly when " + - $"also used to capture unmatched values. Unmatched values:" + Environment.NewLine + - $"test1" + Environment.NewLine + - $"test2", - ex.Message); - } - - [Fact] - public void HasDuplicateCaptureUnmatchedValuesParameters_Throws() - { - // Arrange - var target = new HasDupliateCaptureUnmatchedValuesProperty(); - var parameters = new ParameterViewBuilder().Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"Multiple properties were found on component type '{typeof(HasDupliateCaptureUnmatchedValuesProperty).FullName}' " + - $"with '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. " + - $"Only a single property per type can use '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. " + - $"Properties:" + Environment.NewLine + - $"{nameof(HasDupliateCaptureUnmatchedValuesProperty.CaptureUnmatchedValuesProp1)}" + Environment.NewLine + - $"{nameof(HasDupliateCaptureUnmatchedValuesProperty.CaptureUnmatchedValuesProp2)}", - ex.Message); - } - - [Fact] - public void HasCaptureUnmatchedValuesParameteterWithWrongType_Throws() - { - // Arrange - var target = new HasWrongTypeCaptureUnmatchedValuesProperty(); - var parameters = new ParameterViewBuilder().Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The property '{nameof(HasWrongTypeCaptureUnmatchedValuesProperty.CaptureUnmatchedValuesProp)}' on component type '{typeof(HasWrongTypeCaptureUnmatchedValuesProperty).FullName}' cannot be used with " + - $"'{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}' because it has the wrong type. " + - $"The property must be assignable from 'Dictionary'.", - ex.Message); - } - - [Fact] - public void IncomingNonCascadingValueMatchesCascadingParameter_WithCaptureUnmatchedValues_DoesNotThrow() - { - // Arrange - var target = new HasCaptureUnmatchedValuesPropertyAndCascadingParameter() - { - Cascading = "bye", - }; - var parameters = new ParameterViewBuilder - { - { nameof(HasCaptureUnmatchedValuesPropertyAndCascadingParameter.Cascading), "hi" }, - }.Build(); - - // Act - parameters.SetParameterProperties(target); - - Assert.Collection( - target.CaptureUnmatchedValues, - kvp => - { - Assert.Equal(nameof(HasCaptureUnmatchedValuesPropertyAndCascadingParameter.Cascading), kvp.Key); - Assert.Equal("hi", kvp.Value); - }); - Assert.Equal("bye", target.Cascading); - } - - [Fact] - public void IncomingCascadingValueMatchesNonCascadingParameter_WithCaptureUnmatchedValues_Throws() - { - // Arrange - var target = new HasCaptureUnmatchedValuesProperty(); - var builder = new ParameterViewBuilder(); - builder.Add(nameof(HasInstanceProperties.IntProp), 16, cascading: true); - var parameters = builder.Build(); - - // Act - var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The property '{nameof(HasCaptureUnmatchedValuesProperty.IntProp)}' on component type '{typeof(HasCaptureUnmatchedValuesProperty).FullName}' " + - $"cannot be set using a cascading value.", - ex.Message); - } - - [Fact] - public void IncomingParameterValueMismatchesDeclaredParameterType_Throws() - { - // Arrange - var someObject = new object(); - var parameters = new ParameterViewBuilder - { - { nameof(HasInstanceProperties.IntProp), "string value" }, - }.Build(); - var target = new HasInstanceProperties(); - - // Act - var ex = Assert.Throws( - () => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"Unable to set property '{nameof(HasInstanceProperties.IntProp)}' on object of " + - $"type '{typeof(HasInstanceProperties).FullName}'. The error was: {ex.InnerException.Message}", - ex.Message); - } - - [Fact] - public void PropertyExplicitSetterException_Throws() - { - // Arrange - var target = new HasPropertyWhoseSetterThrows(); - var parameters = new ParameterViewBuilder - { - { nameof(HasPropertyWhoseSetterThrows.StringProp), "anything" }, - }.Build(); - - // Act - var ex = Assert.Throws( - () => parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"Unable to set property '{nameof(HasPropertyWhoseSetterThrows.StringProp)}' on object of " + - $"type '{typeof(HasPropertyWhoseSetterThrows).FullName}'. The error was: {ex.InnerException.Message}", - ex.Message); - } - - [Fact] - public void DeclaredParametersVaryOnlyByCase_Throws() - { - // Arrange - var parameters = new ParameterViewBuilder().Build(); - var target = new HasParametersVaryingOnlyByCase(); - - // Act - var ex = Assert.Throws(() => - parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The type '{typeof(HasParametersVaryingOnlyByCase).FullName}' declares more than one parameter matching the " + - $"name '{nameof(HasParametersVaryingOnlyByCase.MyValue).ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique.", - ex.Message); - } - - [Fact] - public void DeclaredParameterClashesWithInheritedParameter_Throws() - { - // Even when the developer uses 'new' to shadow an inherited property, this is not - // an allowed scenario because there would be no way for the consumer to specify - // both property values, and it's no good leaving the shadowed one unset because the - // base class can legitimately depend on it for correct functioning. - - // Arrange - var parameters = new ParameterViewBuilder().Build(); - var target = new HasParameterClashingWithInherited(); - - // Act - var ex = Assert.Throws(() => - parameters.SetParameterProperties(target)); - - // Assert - Assert.Equal( - $"The type '{typeof(HasParameterClashingWithInherited).FullName}' declares more than one parameter matching the " + - $"name '{nameof(HasParameterClashingWithInherited.IntProp).ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique.", - ex.Message); - } - - [Fact] - public void SupplyingNullWritesDefaultForType() - { - // Arrange - var parameters = new ParameterViewBuilder - { - { nameof(HasInstanceProperties.IntProp), null }, - { nameof(HasInstanceProperties.StringProp), null }, - }.Build(); - var target = new HasInstanceProperties { IntProp = 123, StringProp = "Hello" }; - - // Act - parameters.SetParameterProperties(target); - - // Assert - Assert.Equal(0, target.IntProp); - Assert.Null(target.StringProp); - } - - class HasInstanceProperties - { - [Parameter] public int IntProp { get; set; } - [Parameter] public string StringProp { get; set; } - - [Parameter] public object ObjectProp { get; set; } - - public static string ObjectPropName => nameof(ObjectProp); - public object ObjectPropCurrentValue - { - get => ObjectProp; - set => ObjectProp = value; - } - } - - class HasCascadingParameter - { - [CascadingParameter] public string Cascading { get; set; } - } - - class HasPropertyWithoutParameterAttribute - { - public int IntProp { get; set; } - } - - class HasNonPublicPropertyWithParameterAttribute - { - [Parameter] - internal int IntProp { get; set; } - } - - class HasPropertyWhoseSetterThrows - { - [Parameter] - public string StringProp - { - get => string.Empty; - set => throw new InvalidOperationException("This setter throws"); - } - } - - class HasInheritedProperties : HasInstanceProperties - { - [Parameter] public int DerivedClassIntProp { get; set; } - } - - class BaseType - { - [Parameter] public virtual int VirtualProp { get; set; } - } - - class DerivedType : BaseType - { - public override int VirtualProp { get; set; } - } - - class HasParametersVaryingOnlyByCase - { - [Parameter] public object MyValue { get; set; } - [Parameter] public object Myvalue { get; set; } - } - - class HasParameterClashingWithInherited : HasInstanceProperties - { - [Parameter] public new int IntProp { get; set; } - } - - class HasCaptureUnmatchedValuesProperty - { - [Parameter] public int IntProp { get; set; } - [Parameter] public string StringProp { get; set; } - [Parameter] public object ObjectProp { get; set; } - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary CaptureUnmatchedValues { get; set; } - } - - class HasCaptureUnmatchedValuesPropertyAndCascadingParameter - { - [CascadingParameter] public string Cascading { get; set; } - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary CaptureUnmatchedValues { get; set; } - } - - class HasDupliateCaptureUnmatchedValuesProperty - { - [Parameter(CaptureUnmatchedValues = true)] public Dictionary CaptureUnmatchedValuesProp1 { get; set; } - [Parameter(CaptureUnmatchedValues = true)] public IDictionary CaptureUnmatchedValuesProp2 { get; set; } - } - - class HasWrongTypeCaptureUnmatchedValuesProperty - { - [Parameter(CaptureUnmatchedValues = true)] public KeyValuePair[] CaptureUnmatchedValuesProp { get; set; } - } - - class HasNonPublicCascadingParameter - { - [CascadingParameter] private string Cascading { get; set; } - - public string GetCascadingValue() => Cascading; - } - - class ParameterViewBuilder : IEnumerable - { - private readonly List<(string Name, object Value, bool Cascading)> _keyValuePairs - = new List<(string, object, bool)>(); - - public void Add(string name, object value, bool cascading = false) - => _keyValuePairs.Add((name, value, cascading)); - - public IEnumerator GetEnumerator() - => throw new NotImplementedException(); - - public ParameterView Build() - { - var builder = new RenderTreeBuilder(); - - builder.OpenComponent(0); - foreach (var kvp in _keyValuePairs) - { - if (!kvp.Cascading) - { - builder.AddAttribute(1, kvp.Name, kvp.Value); - } - } - builder.CloseComponent(); - - var view = new ParameterView(ParameterViewLifetime.Unbound, builder.GetFrames().Array, ownerIndex: 0); - - var cascadingParameters = new List(); - foreach (var kvp in _keyValuePairs) - { - if (kvp.Cascading) - { - cascadingParameters.Add(new CascadingParameterState(kvp.Name, new TestCascadingValueProvider(kvp.Value))); - } - } - - return view.WithCascadingParameters(cascadingParameters); - } - } - - private class TestCascadingValueProvider : ICascadingValueComponent - { - public TestCascadingValueProvider(object value) - { - CurrentValue = value; - } - - public object CurrentValue { get; } - - public bool CurrentValueIsFixed => throw new NotImplementedException(); - - public bool CanSupplyValue(Type valueType, string valueName) - { - throw new NotImplementedException(); - } - - public void Subscribe(ComponentState subscriber) - { - throw new NotImplementedException(); - } - - public void Unsubscribe(ComponentState subscriber) - { - throw new NotImplementedException(); - } - } - } -} diff --git a/src/Components/Components/test/ParameterViewTest.cs b/src/Components/Components/test/ParameterViewTest.cs deleted file mode 100644 index 5193e8fe296c..000000000000 --- a/src/Components/Components/test/ParameterViewTest.cs +++ /dev/null @@ -1,399 +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.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Xunit; - -namespace Microsoft.AspNetCore.Components -{ - public partial class ParameterViewTest - { - [Fact] - public void CanInitializeUsingComponentWithNoDescendants() - { - // Arrange - var frames = new[] - { - RenderTreeFrame.ChildComponent(0, typeof(FakeComponent)).WithComponentSubtreeLength(1) - }; - var parameters = new ParameterView(ParameterViewLifetime.Unbound, frames, 0); - - // Assert - Assert.Empty(ToEnumerable(parameters)); - } - - [Fact] - public void CanInitializeUsingElementWithNoDescendants() - { - // Arrange - var frames = new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(1) - }; - var parameters = new ParameterView(ParameterViewLifetime.Unbound, frames, 0); - - // Assert - Assert.Empty(ToEnumerable(parameters)); - } - - [Fact] - public void EnumerationStopsAtEndOfOwnerDescendants() - { - // Arrange - var attribute1Value = new object(); - var attribute2Value = new object(); - var frames = new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), - RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value), - RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value), - // Although RenderTreeBuilder doesn't let you add orphaned attributes like this, - // still want to verify that parameters doesn't attempt to read past the - // end of the owner's descendants - RenderTreeFrame.Attribute(3, "orphaned attribute", "value") - }; - var parameters = new ParameterView(ParameterViewLifetime.Unbound, frames, 0); - - // Assert - Assert.Collection(ToEnumerable(parameters), - AssertParameter("attribute 1", attribute1Value, false), - AssertParameter("attribute 2", attribute2Value, false)); - } - - [Fact] - public void EnumerationStopsAtEndOfOwnerAttributes() - { - // Arrange - var attribute1Value = new object(); - var attribute2Value = new object(); - var frames = new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), - RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value), - RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value), - RenderTreeFrame.Element(3, "child element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(4, "child attribute", "some value") - }; - var parameters = new ParameterView(ParameterViewLifetime.Unbound, frames, 0); - - // Assert - Assert.Collection(ToEnumerable(parameters), - AssertParameter("attribute 1", attribute1Value, false), - AssertParameter("attribute 2", attribute2Value, false)); - } - - [Fact] - public void EnumerationIncludesCascadingParameters() - { - // Arrange - var attribute1Value = new object(); - var attribute2Value = new object(); - var attribute3Value = new object(); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value) - }, 0).WithCascadingParameters(new List - { - new CascadingParameterState("attribute 2", new TestCascadingValue(attribute2Value)), - new CascadingParameterState("attribute 3", new TestCascadingValue(attribute3Value)), - }); - - // Assert - Assert.Collection(ToEnumerable(parameters), - AssertParameter("attribute 1", attribute1Value, false), - AssertParameter("attribute 2", attribute2Value, true), - AssertParameter("attribute 3", attribute3Value, true)); - } - - [Fact] - public void CanTryGetNonExistingValue() - { - // Arrange - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "some other entry", new object()) - }, 0); - - // Act - var didFind = parameters.TryGetValue("nonexisting entry", out var value); - - // Assert - Assert.False(didFind); - Assert.Null(value); - } - - [Fact] - public void CanTryGetExistingValueWithCorrectType() - { - // Arrange - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "my entry", "hello") - }, 0); - - // Act - var didFind = parameters.TryGetValue("my entry", out var value); - - // Assert - Assert.True(didFind); - Assert.Equal("hello", value); - } - - [Fact] - public void CanGetValueOrDefault_WithExistingValue() - { - // Arrange - var myEntryValue = new object(); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "my entry", myEntryValue), - RenderTreeFrame.Attribute(1, "my other entry", new object()) - }, 0); - - // Act - var result = parameters.GetValueOrDefault("my entry"); - - // Assert - Assert.Same(myEntryValue, result); - } - - [Fact] - public void CanGetValueOrDefault_WithMultipleMatchingValues() - { - // Arrange - var myEntryValue = new object(); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), - RenderTreeFrame.Attribute(1, "my entry", myEntryValue), - RenderTreeFrame.Attribute(1, "my entry", new object()), - }, 0); - - // Act - var result = parameters.GetValueOrDefault("my entry"); - - // Assert: Picks first match - Assert.Same(myEntryValue, result); - } - - [Fact] - public void CanGetValueOrDefault_WithNonExistingValue() - { - // Arrange - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "some other entry", new object()) - }, 0).WithCascadingParameters(new List - { - new CascadingParameterState("another entry", new TestCascadingValue(null)) - }); - - // Act - var result = parameters.GetValueOrDefault("nonexisting entry"); - - // Assert - Assert.Equal(default, result); - } - - [Fact] - public void CanGetValueOrDefault_WithNonExistingValueAndExplicitDefault() - { - // Arrange - var explicitDefaultValue = new DateTime(2018, 3, 20); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "some other entry", new object()) - }, 0); - - // Act - var result = parameters.GetValueOrDefault("nonexisting entry", explicitDefaultValue); - - // Assert - Assert.Equal(explicitDefaultValue, result); - } - - [Fact] - public void ThrowsIfTryGetExistingValueWithIncorrectType() - { - // Arrange - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "my entry", "hello") - }, 0); - - // Act/Assert - Assert.Throws(() => - { - parameters.TryGetValue("my entry", out var value); - }); - } - - [Fact] - public void FromDictionary_CanBeInitializedWithEmptyDictionary() - { - // Arrange - var dictionary = new Dictionary(); - - // Act - var collection = ParameterView.FromDictionary(dictionary); - - // Assert - Assert.Empty(collection.ToDictionary()); - } - - [Fact] - public void FromDictionary_RoundTrips() - { - // Arrange - var dictionary = new Dictionary - { - ["IntValue"] = 1, - ["StringValue"] = "String" - }; - - // Act - var collection = ParameterView.FromDictionary(dictionary); - - // Assert - Assert.Equal(dictionary, collection.ToDictionary()); - } - - - [Fact] - public void CanConvertToReadOnlyDictionary() - { - // Arrange - var entry2Value = new object(); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), - RenderTreeFrame.Attribute(0, "entry 1", "value 1"), - RenderTreeFrame.Attribute(0, "entry 2", entry2Value), - }, 0); - - // Act - IReadOnlyDictionary dict = parameters.ToDictionary(); - - // Assert - Assert.Collection(dict, - entry => - { - Assert.Equal("entry 1", entry.Key); - Assert.Equal("value 1", entry.Value); - }, - entry => - { - Assert.Equal("entry 2", entry.Key); - Assert.Same(entry2Value, entry.Value); - }); - } - - [Fact] - public void CanGetValueOrDefault_WithMatchingCascadingParameter() - { - // Arrange - var myEntryValue = new object(); - var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] - { - RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), - RenderTreeFrame.Attribute(1, "unrelated value", new object()) - }, 0).WithCascadingParameters(new List - { - new CascadingParameterState("unrelated value 2", new TestCascadingValue(null)), - new CascadingParameterState("my entry", new TestCascadingValue(myEntryValue)), - new CascadingParameterState("unrelated value 3", new TestCascadingValue(null)), - }); - - // Act - var result = parameters.GetValueOrDefault("my entry"); - - // Assert - Assert.Same(myEntryValue, result); - } - - [Fact] - public void CannotReadAfterLifetimeExpiry() - { - // Arrange - var builder = new RenderBatchBuilder(); - var lifetime = new ParameterViewLifetime(builder); - var frames = new[] - { - RenderTreeFrame.ChildComponent(0, typeof(FakeComponent)).WithComponentSubtreeLength(1) - }; - var parameterView = new ParameterView(lifetime, frames, 0); - - // Act - builder.InvalidateParameterViews(); - - // Assert - Assert.Throws(() => parameterView.GetEnumerator()); - Assert.Throws(() => parameterView.GetValueOrDefault("anything")); - Assert.Throws(() => parameterView.SetParameterProperties(new object())); - Assert.Throws(() => parameterView.ToDictionary()); - var ex = Assert.Throws(() => parameterView.TryGetValue("anything", out _)); - - // It's enough to assert about one of the messages - Assert.Equal($"The {nameof(ParameterView)} instance can no longer be read because it has expired. {nameof(ParameterView)} can only be read synchronously and must not be stored for later use.", ex.Message); - } - - private Action AssertParameter(string expectedName, object expectedValue, bool expectedIsCascading) - { - return parameter => - { - Assert.Equal(expectedName, parameter.Name); - Assert.Same(expectedValue, parameter.Value); - Assert.Equal(expectedIsCascading, parameter.Cascading); - }; - } - - public IEnumerable ToEnumerable(ParameterView parameters) - { - foreach (var item in parameters) - { - yield return item; - } - } - - private class FakeComponent : IComponent - { - public void Attach(RenderHandle renderHandle) - => throw new NotImplementedException(); - - public Task SetParametersAsync(ParameterView parameters) - => throw new NotImplementedException(); - } - - private class TestCascadingValue : ICascadingValueComponent - { - public TestCascadingValue(object value) - { - CurrentValue = value; - } - - public object CurrentValue { get; } - - public bool CurrentValueIsFixed => false; - - public bool CanSupplyValue(Type valueType, string valueName) - => throw new NotImplementedException(); - - public void Subscribe(ComponentState subscriber) - => throw new NotImplementedException(); - - public void Unsubscribe(ComponentState subscriber) - => throw new NotImplementedException(); - } - } -} diff --git a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs b/src/Components/Components/test/RenderTreeDiffBuilderTest.cs deleted file mode 100644 index 28f617eba268..000000000000 --- a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs +++ /dev/null @@ -1,2309 +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.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.Logging.Abstractions; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class RenderTreeDiffBuilderTest : IDisposable - { - private readonly Renderer renderer; - private readonly RenderTreeBuilder oldTree; - private readonly RenderTreeBuilder newTree; - private RenderBatchBuilder batchBuilder; - - public RenderTreeDiffBuilderTest() - { - renderer = new FakeRenderer(); - oldTree = new RenderTreeBuilder(); - newTree = new RenderTreeBuilder(); - } - - void IDisposable.Dispose() - { - renderer.Dispose(); - ((IDisposable)oldTree).Dispose(); - ((IDisposable)newTree).Dispose(); - batchBuilder?.Dispose(); - } - - [Theory] - [MemberData(nameof(RecognizesEquivalentFramesAsSameCases))] - public void RecognizesEquivalentFramesAsSame(RenderFragment appendFragment) - { - // Arrange - appendFragment(oldTree); - appendFragment(newTree); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true); - - // Assert - Assert.Empty(result.Edits); - } - - public static IEnumerable RecognizesEquivalentFramesAsSameCases() - => new RenderFragment[] - { - builder => builder.AddContent(0, "Hello"), - builder => - { - builder.OpenElement(0, "Some Element"); - builder.CloseElement(); - }, - builder => - { - builder.OpenElement(0, "Some Element"); - builder.AddAttribute(1, "My attribute", "My value"); - builder.CloseElement(); - }, - builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - } - }.Select(x => new object[] { x }); - - [Fact] - public void RecognizesNewItemsBeingInserted() - { - // Arrange - oldTree.AddContent(0, "text0"); - oldTree.AddContent(2, "text2"); - newTree.AddContent(0, "text0"); - newTree.AddContent(1, "text1"); - newTree.AddContent(2, "text2"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - AssertFrame.Text(referenceFrames[0], "text1", 1); - }); - } - - [Fact] - public void RecognizesOldItemsBeingRemoved() - { - // Arrange - oldTree.AddContent(0, "text0"); - oldTree.AddContent(1, "text1"); - oldTree.AddContent(2, "text2"); - newTree.AddContent(0, "text0"); - newTree.AddContent(2, "text2"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RecognizesKeyedElementInsertions() - { - // Arrange - oldTree.OpenElement(0, "container"); - oldTree.SetKey("retained key"); - oldTree.AddContent(1, "Existing"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "container"); - newTree.SetKey("new key"); - newTree.AddContent(1, "Inserted"); - newTree.CloseElement(); - - newTree.OpenElement(0, "container"); - newTree.SetKey("retained key"); - newTree.AddContent(1, "Existing"); - newTree.CloseElement(); - - // Without the key, it would change the text "Existing" to "Inserted", then insert a new "Existing" below it - // With the key, it just inserts a new "Inserted" at the top - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ElementKey); - }); - } - - [Fact] - public void RecognizesKeyedElementDeletions() - { - // Arrange - oldTree.OpenElement(0, "container"); - oldTree.SetKey("will delete"); - oldTree.AddContent(1, "First"); - oldTree.CloseElement(); - - oldTree.OpenElement(0, "container"); - oldTree.SetKey("will retain"); - oldTree.AddContent(1, "Second"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "container"); - newTree.SetKey("will retain"); - newTree.AddContent(1, "Second"); - newTree.CloseElement(); - - // Without the key, it changes the text content of "First" to "Second", then deletes the other "Second" - // With the key, it just deletes "First" - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0)); - } - - [Fact] - public void RecognizesSimultaneousKeyedElementInsertionsAndDeletions() - { - // Arrange - oldTree.OpenElement(0, "container"); - oldTree.SetKey("original key"); - oldTree.AddContent(1, "Original"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "container"); - newTree.SetKey("new key"); - newTree.AddContent(1, "Inserted"); - newTree.CloseElement(); - - // Without the key, it would change the text "Original" to "Inserted" - // With the key, it deletes the old element and inserts the new element - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ElementKey); - }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RecognizesKeyedComponentInsertions() - { - // Arrange - oldTree.OpenComponent(0); - oldTree.SetKey("retained key"); - oldTree.AddAttribute(1, "ParamName", "Param old value"); - oldTree.CloseComponent(); - using var initial = new RenderTreeBuilder(); - GetRenderedBatch(initial, oldTree, false); // Assign initial IDs - var oldComponent = GetComponents(oldTree).Single(); - - newTree.OpenComponent(0); - newTree.SetKey("new key"); - newTree.AddAttribute(1, "ParamName", "New component param value"); - newTree.CloseComponent(); - - newTree.OpenComponent(0); - newTree.SetKey("retained key"); - newTree.AddAttribute(1, "ParamName", "Param new value"); - newTree.CloseComponent(); - - // Without the key, it would modify the param on the first component, - // then insert a new second component. - // With the key, it inserts a new first component, then modifies the - // param on the second component. - - // Act - var batchBuilder = GetRenderedBatch(initializeFromFrames: false); - var newComponents = GetComponents(newTree); - - // Assert: Inserts new component at position 0 - Assert.Equal(1, batchBuilder.UpdatedComponents.Count); - Assert.Collection(batchBuilder.UpdatedComponents.Array[0].Edits, - entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0)); - - // Assert: Retains old component instance in position 1, and updates its params - Assert.Same(oldComponent, newComponents[1]); - Assert.Equal(2, oldComponent.SetParametersCallCount); - } - - [Fact] - public void RecognizesKeyedComponentDeletions() - { - // Arrange - oldTree.OpenComponent(0); - oldTree.SetKey("will delete"); - oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Anything"); - oldTree.CloseComponent(); - - oldTree.OpenComponent(0); - oldTree.SetKey("will retain"); - oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Retained param value"); - oldTree.CloseComponent(); - - // Instantiate initial components - using var initial = new RenderTreeBuilder(); - GetRenderedBatch(initial, oldTree, false); - var oldComponents = GetComponents(oldTree); - - newTree.OpenComponent(0); - newTree.SetKey("will retain"); - newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Retained param value"); - newTree.CloseComponent(); - - // Without the key, it updates the param on the first component, then - // deletes the second. - // With the key, it just deletes the first. - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - var newComponent = GetComponents(newTree).Single(); - - // Assert - Assert.Same(oldComponents[1], newComponent); - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0)); - } - - [Fact] - public void RecognizesSimultaneousKeyedComponentInsertionsAndDeletions() - { - // Arrange - oldTree.OpenComponent(0); - oldTree.SetKey("original key"); - oldTree.CloseComponent(); - - // Instantiate initial component - using var renderTreeBuilder = new RenderTreeBuilder(); - GetRenderedBatch(renderTreeBuilder, oldTree, false); - var oldComponent = GetComponents(oldTree).Single(); - Assert.NotNull(oldComponent); - - newTree.OpenComponent(0); - newTree.SetKey("new key"); - newTree.CloseComponent(); - - // Without the key, it would retain the component - // With the key, it deletes the old component and inserts the new component - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - var newComponent = GetComponents(newTree).Single(); - - // Assert - Assert.NotNull(newComponent); - Assert.NotSame(oldComponent, newComponent); - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ComponentKey); - }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RejectsClashingKeysInOldTree() - { - // Arrange - AddWithKey(oldTree, "key1", "attrib1a"); - AddWithKey(oldTree, "key2", "attrib2"); - AddWithKey(oldTree, "key1", "attrib3"); - - AddWithKey(newTree, "key1", "attrib1b"); - AddWithKey(newTree, "key2", "attrib2"); - AddWithKey(newTree, "key3", "attrib3"); - - // Act/Assert - var ex = Assert.Throws(() => GetSingleUpdatedComponent()); - Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message); - } - - [Fact] - public void RejectsClashingKeysInNewTree() - { - // Arrange - AddWithKey(oldTree, "key1", "attrib1a"); - AddWithKey(oldTree, "key2", "attrib2"); - AddWithKey(oldTree, "key3", "attrib3"); - - AddWithKey(newTree, "key1", "attrib1b"); - AddWithKey(newTree, "key2", "attrib2"); - AddWithKey(newTree, "key1", "attrib3"); - - // Act/Assert - var ex = Assert.Throws(() => GetSingleUpdatedComponent()); - Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message); - } - - [Fact] - public void RejectsClashingKeysEvenIfAllPairsMatch() - { - // This sort of scenario would happen if you accidentally used a constant value for @key - - // Arrange - AddWithKey(oldTree, "key1", "attrib1a"); - AddWithKey(oldTree, "key1", "attrib1b"); - - AddWithKey(newTree, "key1", "attrib1a"); - AddWithKey(newTree, "key1", "attrib1b"); - - // Act/Assert - var ex = Assert.Throws(() => GetSingleUpdatedComponent()); - Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message); - } - - [Fact] - public void HandlesInsertionOfUnkeyedItemsAroundKey() - { - // The fact that the new sequence numbers are descending makes this - // problematic if it prefers matching by sequence over key. - // However, since the policy is to prefer key over sequence, it works OK. - - // Arrange - oldTree.OpenElement(1, "el"); - oldTree.SetKey("some key"); - oldTree.CloseElement(); - - newTree.OpenElement(2, "other"); - newTree.CloseElement(); - - newTree.OpenElement(1, "el"); - newTree.SetKey("some key"); - newTree.CloseElement(); - - newTree.OpenElement(0, "other 2"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 0), - edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 2)); - } - - [Fact] - public void HandlesDeletionOfUnkeyedItemsAroundKey() - { - // The fact that the old sequence numbers are descending makes this - // problematic if it prefers matching by sequence over key. - // However, since the policy is to prefer key over sequence, it works OK. - - // Arrange - oldTree.OpenElement(2, "other"); - oldTree.CloseElement(); - - oldTree.OpenElement(1, "el"); - oldTree.SetKey("some key"); - oldTree.CloseElement(); - - oldTree.OpenElement(0, "other 2"); - oldTree.CloseElement(); - - newTree.OpenElement(1, "el"); - newTree.SetKey("some key"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 0), - edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void HandlesKeyBeingAdded() - { - // This is an anomolous situation that can't occur with .razor components. - // It represents the case where, for the same sequence number, we have an - // old frame without a key and a new frame with a key. - - // Arrange - oldTree.OpenElement(0, "el"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "el"); - newTree.SetKey("some key"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - // Insert new - edit => - { - AssertEdit(edit, RenderTreeEditType.PrependFrame, 0); - Assert.Equal("some key", referenceFrames[edit.ReferenceFrameIndex].ElementKey); - }, - // Delete old - edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void HandlesKeyBeingRemoved() - { - // This is an anomolous situation that can't occur with .razor components. - // It represents the case where, for the same sequence number, we have an - // old frame with a key and a new frame without a key. - - // Arrange - oldTree.OpenElement(0, "el"); - oldTree.SetKey("some key"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "el"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - // Insert new - edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 0), - // Delete old - edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RecognizesTrailingSequenceWithinLoopBlockBeingRemoved() - { - // Arrange - oldTree.AddContent(0, "x"); // Loop start - oldTree.AddContent(1, "x"); // Will be removed - oldTree.AddContent(2, "x"); // Will be removed - oldTree.AddContent(0, "x"); // Loop start - newTree.AddContent(0, "x"); // Loop start - newTree.AddContent(0, "x"); // Loop start - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RecognizesTrailingSequenceWithinLoopBlockBeingAppended() - { - // Arrange - oldTree.AddContent(10, "x"); // Loop start - oldTree.AddContent(10, "x"); // Loop start - newTree.AddContent(10, "x"); // Loop start - newTree.AddContent(11, "x"); // Will be added - newTree.AddContent(12, "x"); // Will be added - newTree.AddContent(10, "x"); // Loop start - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); - Assert.Equal(1, entry.ReferenceFrameIndex); - }); - AssertFrame.Text(referenceFrames[0], "x", 11); - AssertFrame.Text(referenceFrames[1], "x", 12); - } - - [Fact] - public void RecognizesTrailingLoopBlockBeingRemoved() - { - // Arrange - oldTree.AddContent(0, "x"); - oldTree.AddContent(1, "x"); - oldTree.AddContent(0, "x"); // Will be removed - oldTree.AddContent(1, "x"); // Will be removed - newTree.AddContent(0, "x"); - newTree.AddContent(1, "x"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2), - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2)); - } - - [Fact] - public void RecognizesTrailingLoopBlockBeingAdded() - { - // Arrange - oldTree.AddContent(10, "x"); - oldTree.AddContent(11, "x"); - newTree.AddContent(10, "x"); - newTree.AddContent(11, "x"); - newTree.AddContent(10, "x"); // Will be added - newTree.AddContent(11, "x"); // Will be added - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 3); - Assert.Equal(1, entry.ReferenceFrameIndex); - }); - AssertFrame.Text(referenceFrames[0], "x", 10); - AssertFrame.Text(referenceFrames[1], "x", 11); - } - - [Fact] - public void RecognizesLeadingLoopBlockItemsBeingAdded() - { - // Arrange - oldTree.AddContent(12, "x"); - oldTree.AddContent(12, "x"); // Note that the '0' and '1' items are not present on this iteration - newTree.AddContent(12, "x"); - newTree.AddContent(10, "x"); - newTree.AddContent(11, "x"); - newTree.AddContent(12, "x"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); - Assert.Equal(1, entry.ReferenceFrameIndex); - }); - AssertFrame.Text(referenceFrames[0], "x", 10); - AssertFrame.Text(referenceFrames[1], "x", 11); - } - - [Fact] - public void RecognizesLeadingLoopBlockItemsBeingRemoved() - { - // Arrange - oldTree.AddContent(2, "x"); - oldTree.AddContent(0, "x"); - oldTree.AddContent(1, "x"); - oldTree.AddContent(2, "x"); - newTree.AddContent(2, "x"); - newTree.AddContent(2, "x"); // Note that the '0' and '1' items are not present on this iteration - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void HandlesAdjacentItemsBeingRemovedAndInsertedAtOnce() - { - // Arrange - oldTree.AddContent(0, "text"); - newTree.AddContent(1, "text"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0), - entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0)); - } - - [Fact] - public void RecognizesTextUpdates() - { - // Arrange - oldTree.AddContent(123, "old text 1"); - oldTree.AddContent(182, "old text 2"); - newTree.AddContent(123, "new text 1"); - newTree.AddContent(182, "new text 2"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 1); - Assert.Equal(1, entry.ReferenceFrameIndex); - }); - } - - [Fact] - public void RecognizesMarkupChanges() - { - // Arrange - oldTree.AddMarkupContent(1, "preserved"); - oldTree.AddMarkupContent(3, "will be updated"); - oldTree.AddMarkupContent(4, "will be removed"); - newTree.AddMarkupContent(1, "preserved"); - newTree.AddMarkupContent(2, "was inserted"); - newTree.AddMarkupContent(3, "was updated"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("was inserted", referenceFrames[entry.ReferenceFrameIndex].MarkupContent); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateMarkup, 2); - Assert.Equal(1, entry.ReferenceFrameIndex); - Assert.Equal("was updated", referenceFrames[entry.ReferenceFrameIndex].MarkupContent); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveFrame, 3); - }); - } - - [Fact] - public void RecognizesElementNameChangesAtSameSequenceNumber() - { - // Note: It's not possible to trigger this scenario from a Razor component, because - // a given source sequence can only have a single fixed element name. We might later - // decide just to throw in this scenario, since it's unnecessary to support it. - - // Arrange - oldTree.OpenElement(123, "old element"); - oldTree.CloseElement(); - newTree.OpenElement(123, "new element"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0), - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - } - - [Fact] - public void RecognizesComponentTypeChangesAtSameSequenceNumber() - { - // Arrange - oldTree.OpenComponent(123); - oldTree.CloseComponent(); - using var initial = new RenderTreeBuilder(); - GetRenderedBatch(initial, oldTree, false); // Assign initial IDs - newTree.OpenComponent(123); - newTree.CloseComponent(); - using var batchBuilder = new RenderBatchBuilder(); - - // Act - var diff = RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, oldTree.GetFrames(), newTree.GetFrames()); - - // Assert: We're going to dispose the old component and render the new one - Assert.Equal(new[] { 0 }, batchBuilder.ComponentDisposalQueue); - Assert.Collection(diff.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0), - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.IsType(batchBuilder.ReferenceFramesBuffer.Buffer[entry.ReferenceFrameIndex].Component); - }); - } - - [Fact] - public void RecognizesAttributesAdded() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "existing", "existing value"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "existing", "existing value"); - newTree.AddAttribute(2, "added", "added value"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - AssertFrame.Attribute(referenceFrames[0], "added", "added value"); - } - - [Fact] - public void RecognizesAttributesRemoved() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "will be removed", "will be removed value"); - oldTree.AddAttribute(2, "will survive", "surviving value"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(2, "will survive", "surviving value"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("will be removed", entry.RemovedAttributeName); - }); - } - - [Fact] - public void RecognizesAttributeStringValuesChanged() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "will remain", "will remain value"); - oldTree.AddAttribute(2, "will change", "will change value"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "will remain", "will remain value"); - newTree.AddAttribute(2, "will change", "did change value"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - AssertFrame.Attribute(referenceFrames[0], "will change", "did change value"); - } - - [Fact] - public void RecognizesAttributeEventHandlerValuesChanged() - { - // Arrange - Action retainedHandler = _ => { }; - Action removedHandler = _ => { }; - Action addedHandler = _ => { }; - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "onfoo", retainedHandler); - oldTree.AddAttribute(2, "onbar", removedHandler); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "onfoo", retainedHandler); - newTree.AddAttribute(2, "onbar", addedHandler); - newTree.CloseElement(); - - // Act - var (result, referenceFrames, batchBuilder) = GetSingleUpdatedComponentWithBatch(initializeFromFrames: true); - var removedEventHandlerFrame = oldTree.GetFrames().Array[2]; - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - AssertFrame.Attribute(referenceFrames[0], "onbar", addedHandler); - Assert.NotEqual(default, removedEventHandlerFrame.AttributeEventHandlerId); - Assert.Equal( - new[] { removedEventHandlerFrame.AttributeEventHandlerId }, - batchBuilder.DisposedEventHandlerIDs.AsEnumerable()); - } - - [Fact] - public void RecognizesAttributeNamesChangedAtSameSourceSequence() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "oldname", "same value"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "newname", "same value"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("oldname", entry.RemovedAttributeName); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - AssertFrame.Attribute(referenceFrames[0], "newname", "same value"); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeAddedAtStart() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr2", "value2"); - oldTree.AddAttribute(0, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr1", "value1"); - newTree.AddAttribute(0, "attr2", "value2"); - newTree.AddAttribute(0, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr1", 0)); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeAddedInMiddle() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr1", "value1"); - oldTree.AddAttribute(0, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr1", "value1"); - newTree.AddAttribute(0, "attr2", "value2"); - newTree.AddAttribute(0, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr2", 0)); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeAddedAtEnd() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr1", "value1"); - oldTree.AddAttribute(0, "attr2", "value2"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr1", "value1"); - newTree.AddAttribute(0, "attr2", "value2"); - newTree.AddAttribute(0, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr3", 0)); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeAddedAtStart() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(2, "attr2", "value2"); - oldTree.AddAttribute(3, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "attr1", "value1"); - newTree.AddAttribute(2, "attr2", "value2"); - newTree.AddAttribute(3, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr1", 1)); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeAddedInMiddle() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "attr1", "value1"); - oldTree.AddAttribute(3, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "attr1", "value1"); - newTree.AddAttribute(2, "attr2", "value2"); - newTree.AddAttribute(3, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr2", 2)); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeAddedAtEnd() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "attr1", "value1"); - oldTree.AddAttribute(2, "attr2", "value2"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "attr1", "value1"); - newTree.AddAttribute(2, "attr2", "value2"); - newTree.AddAttribute(3, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.SetAttribute, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - - Assert.Collection( - referenceFrames, - frame => AssertFrame.Attribute(frame, "attr3", 3)); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeRemovedAtStart() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr1", "value1"); - oldTree.AddAttribute(0, "attr2", "value2"); - oldTree.AddAttribute(0, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr2", "value2"); - newTree.AddAttribute(0, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr1", entry.RemovedAttributeName); - }); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeRemovedInMiddle() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr1", "value1"); - oldTree.AddAttribute(0, "attr2", "value2"); - oldTree.AddAttribute(0, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr1", "value1"); - newTree.AddAttribute(0, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr2", entry.RemovedAttributeName); - }); - } - - [Fact] - public void AttributeDiff_WithSameSequenceNumber_AttributeRemovedAtEnd() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "attr1", "value1"); - oldTree.AddAttribute(0, "attr2", "value2"); - oldTree.AddAttribute(0, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "attr1", "value1"); - newTree.AddAttribute(0, "attr2", "value2"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr3", entry.RemovedAttributeName); - }); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeRemovedAtStart() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "attr1", "value1"); - oldTree.AddAttribute(2, "attr2", "value2"); - oldTree.AddAttribute(3, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(2, "attr2", "value2"); - newTree.AddAttribute(3, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr1", entry.RemovedAttributeName); - }); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeRemovedInMiddle() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "attr1", "value1"); - oldTree.AddAttribute(2, "attr2", "value2"); - oldTree.AddAttribute(3, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "attr1", "value1"); - newTree.AddAttribute(3, "attr3", "value3"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr2", entry.RemovedAttributeName); - }); - } - - [Fact] - public void AttributeDiff_WithSequentialSequenceNumber_AttributeRemovedAtEnd() - { - // Arrange - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "attr1", "value1"); - oldTree.AddAttribute(2, "attr2", "value2"); - oldTree.AddAttribute(3, "attr3", "value3"); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "attr1", "value1"); - newTree.AddAttribute(2, "attr2", "value2"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection( - result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0); - Assert.Equal("attr3", entry.RemovedAttributeName); - }); - } - - [Fact] - public void DiffsElementsHierarchically() - { - // Arrange - oldTree.AddContent(09, "unrelated"); - oldTree.OpenElement(10, "root"); - oldTree.OpenElement(11, "child"); - oldTree.OpenElement(12, "grandchild"); - oldTree.AddContent(13, "grandchild old text"); - oldTree.CloseElement(); - oldTree.CloseElement(); - oldTree.CloseElement(); - - newTree.AddContent(09, "unrelated"); - newTree.OpenElement(10, "root"); - newTree.OpenElement(11, "child"); - newTree.OpenElement(12, "grandchild"); - newTree.AddContent(13, "grandchild new text"); - newTree.CloseElement(); - newTree.CloseElement(); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 1), - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 0), - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 0), - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0), - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0), - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0)); - AssertFrame.Text(referenceFrames[0], "grandchild new text", 13); - } - - [Fact] - public void SkipsUnmodifiedSubtrees() - { - // Arrange - oldTree.OpenElement(10, "root"); - oldTree.AddContent(11, "Text that will change"); - oldTree.OpenElement(12, "Subtree that will not change"); - oldTree.OpenElement(13, "Another"); - oldTree.AddContent(14, "Text that will not change"); - oldTree.CloseElement(); - oldTree.CloseElement(); - oldTree.CloseElement(); - - newTree.OpenElement(10, "root"); - newTree.AddContent(11, "Text that has changed"); - newTree.OpenElement(12, "Subtree that will not change"); - newTree.OpenElement(13, "Another"); - newTree.AddContent(14, "Text that will not change"); - newTree.CloseElement(); - newTree.CloseElement(); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 0), - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0)); - AssertFrame.Text(referenceFrames[0], "Text that has changed", 11); - } - - [Fact] - public void SkipsUnmodifiedTrailingSiblings() - { - // Arrange - oldTree.AddContent(10, "text1"); - oldTree.AddContent(11, "text2"); - oldTree.AddContent(12, "text3"); - oldTree.AddContent(13, "text4"); - newTree.AddContent(10, "text1"); - newTree.AddContent(11, "text2modified"); - newTree.AddContent(12, "text3"); - newTree.AddContent(13, "text4"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - AssertFrame.Text(referenceFrames[0], "text2modified", 11); - } - - [Fact] - public void PassesThroughRegionsInsidePrependedElements() - { - // Arrange - oldTree.AddContent(0, "Will not change"); - newTree.AddContent(0, "Will not change"); - newTree.OpenElement(1, "root"); - newTree.OpenRegion(2); - newTree.AddContent(0, "text1"); - newTree.CloseRegion(); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - }); - Assert.Collection(referenceFrames, - frame => AssertFrame.Element(frame, "root", 3, 1), - frame => AssertFrame.Region(frame, 2, 2), - frame => AssertFrame.Text(frame, "text1")); - } - - [Fact] - public void RecognizesInsertedRegions() - { - // Arrange - oldTree.AddContent(1, "Start"); - oldTree.AddContent(3, "End"); - newTree.AddContent(1, "Start"); - newTree.OpenRegion(2); - newTree.AddContent(4, "Text inside region"); // Sequence number is unrelated to outside the region - newTree.OpenRegion(5); - newTree.AddContent(6, "Text inside nested region"); - newTree.CloseRegion(); - newTree.CloseRegion(); - newTree.AddContent(3, "End"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - AssertFrame.Text( - referenceFrames[entry.ReferenceFrameIndex], "Text inside region"); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); - AssertFrame.Text( - referenceFrames[entry.ReferenceFrameIndex], "Text inside nested region"); - }); - } - - [Fact] - public void RecognizesRemovedRegions() - { - // Arrange - oldTree.AddContent(1, "Start"); - oldTree.OpenRegion(2); - oldTree.AddContent(4, "Text inside region"); // Sequence number is unrelated to outside the region - oldTree.OpenRegion(5); - oldTree.AddContent(6, "Text inside nested region"); - oldTree.CloseRegion(); - oldTree.CloseRegion(); - oldTree.AddContent(3, "End"); - newTree.AddContent(1, "Start"); - newTree.AddContent(3, "End"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void RecognizesEquivalentRegions() - { - // Arrange - oldTree.AddContent(1, "Start"); - oldTree.OpenRegion(2); - oldTree.AddContent(4, "Text inside region"); - oldTree.AddContent(5, "Text to move"); - oldTree.OpenRegion(6); - oldTree.CloseRegion(); - oldTree.CloseRegion(); - oldTree.AddContent(3, "End"); - newTree.AddContent(1, "Start"); - newTree.OpenRegion(2); - newTree.AddContent(4, "Changed text inside region"); - newTree.OpenRegion(6); - newTree.AddContent(5, "Text to move"); // Although it's the same sequence and content, it's now in a different region so not the same - newTree.CloseRegion(); - newTree.CloseRegion(); - newTree.AddContent(3, "End"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 1); - AssertFrame.Text( - referenceFrames[entry.ReferenceFrameIndex], "Changed text inside region"); - }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2), - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); - AssertFrame.Text( - referenceFrames[entry.ReferenceFrameIndex], "Text to move"); - }); - } - - [Fact] - public void InstantiatesChildComponentsForInsertedFrames() - { - // Arrange - oldTree.AddContent(10, "text1"); // 0: text1 - oldTree.OpenElement(11, "container"); // 1: - oldTree.CloseElement(); // - newTree.AddContent(10, "text1"); // 0: text1 - newTree.OpenElement(11, "container"); // 1: - newTree.OpenComponent(12); // 2: - newTree.CloseComponent(); // - newTree.OpenComponent(13); // 3: - newTree.CloseComponent(); // - newTree.CloseElement(); // - - // Act - var renderBatch = GetRenderedBatch(); - - // Assert - var diff = renderBatch.UpdatedComponents.AsEnumerable().Single(); - Assert.Collection(diff.Edits, - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 1), - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - }, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(1, entry.ReferenceFrameIndex); - }, - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0)); - AssertFrame.ComponentWithInstance(renderBatch.ReferenceFrames.Array[0], 0, null, 12); - AssertFrame.ComponentWithInstance(renderBatch.ReferenceFrames.Array[1], 1, null, 13); - } - - [Fact] - public void SetsParametersOnChildComponents() - { - // Arrange - var testObject = new object(); - newTree.OpenComponent(0); - newTree.AddAttribute(1, nameof(FakeComponent.IntProperty), 123); - newTree.AddAttribute(2, nameof(FakeComponent.StringProperty), "some string"); - newTree.AddAttribute(3, nameof(FakeComponent.ObjectProperty), testObject); - newTree.CloseComponent(); - - // Act - var renderBatch = GetRenderedBatch(); - var componentInstance = newTree.GetFrames().AsEnumerable().First().Component as FakeComponent; - - // Assert - Assert.Equal(1, renderBatch.UpdatedComponents.Count); - var rootComponentDiff = renderBatch.UpdatedComponents.Array[0]; - AssertEdit(rootComponentDiff.Edits.Single(), RenderTreeEditType.PrependFrame, 0); - Assert.NotNull(componentInstance); - Assert.Equal(123, componentInstance.IntProperty); - Assert.Equal("some string", componentInstance.StringProperty); - Assert.Same(testObject, componentInstance.ObjectProperty); - } - - [Fact] - public void RetainsChildComponentsForExistingFrames() - { - // Arrange - oldTree.AddContent(10, "text1"); // 0: text1 - oldTree.OpenElement(11, "container"); // 1: - oldTree.OpenComponent(12); // 2: - oldTree.CloseComponent(); // - oldTree.OpenComponent(13); // 3: - oldTree.CloseComponent(); // - oldTree.CloseElement(); // - newTree.AddContent(10, "text1"); // 0: text1 - newTree.OpenElement(11, "container"); // 1: - newTree.OpenComponent(12); // 2: - newTree.CloseComponent(); // - newTree.OpenComponent(13); // 3: - newTree.CloseComponent(); // - newTree.CloseElement(); // - - using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTreeBuilder.GetFrames(), oldTree.GetFrames()); - var originalFakeComponentInstance = oldTree.GetFrames().Array[2].Component; - var originalFakeComponent2Instance = oldTree.GetFrames().Array[3].Component; - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - var newFrame1 = newTree.GetFrames().Array[2]; - var newFrame2 = newTree.GetFrames().Array[3]; - - // Assert - Assert.Empty(result.Edits); - Assert.Equal(0, newFrame1.ComponentId); - Assert.Equal(1, newFrame2.ComponentId); - Assert.Same(originalFakeComponentInstance, newFrame1.Component); - Assert.Same(originalFakeComponent2Instance, newFrame2.Component); - } - - [Fact] - public void PreservesEventHandlerIdsForRetainedEventHandlers() - { - // Arrange - Action retainedHandler = _ => { }; - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(1, "ontest", retainedHandler); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(1, "ontest", retainedHandler); - newTree.CloseElement(); - - // Act - var (result, referenceFrames, batchBuilder) = GetSingleUpdatedComponentWithBatch(initializeFromFrames: true); - var oldAttributeFrame = oldTree.GetFrames().Array[1]; - var newAttributeFrame = newTree.GetFrames().Array[1]; - - // Assert - Assert.Empty(result.Edits); - AssertFrame.Attribute(oldAttributeFrame, "ontest", retainedHandler); - AssertFrame.Attribute(newAttributeFrame, "ontest", retainedHandler); - Assert.NotEqual(default, oldAttributeFrame.AttributeEventHandlerId); - Assert.Equal(oldAttributeFrame.AttributeEventHandlerId, newAttributeFrame.AttributeEventHandlerId); - Assert.Empty(batchBuilder.DisposedEventHandlerIDs.AsEnumerable()); - } - - [Fact] - public void PreservesEventHandlerIdsForRetainedEventHandlers_SlowPath() - { - // Arrange - Action retainedHandler = _ => { }; - oldTree.OpenElement(0, "My element"); - oldTree.AddAttribute(0, "ontest", retainedHandler); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddAttribute(0, "another-attribute", "go down the slow path please"); - newTree.AddAttribute(0, "ontest", retainedHandler); - newTree.CloseElement(); - - // Act - var (result, referenceFrames, batchBuilder) = GetSingleUpdatedComponentWithBatch(initializeFromFrames: true); - var oldAttributeFrame = oldTree.GetFrames().Array[1]; - var newAttributeFrame = newTree.GetFrames().Array[2]; - - // Assert - Assert.Single(result.Edits); - AssertFrame.Attribute(oldAttributeFrame, "ontest", retainedHandler); - AssertFrame.Attribute(newAttributeFrame, "ontest", retainedHandler); - Assert.NotEqual(default, oldAttributeFrame.AttributeEventHandlerId); - Assert.Equal(oldAttributeFrame.AttributeEventHandlerId, newAttributeFrame.AttributeEventHandlerId); - Assert.Empty(batchBuilder.DisposedEventHandlerIDs.AsEnumerable()); - } - - [Fact] - public void SetsUpdatedParametersOnChildComponents() - { - // Arrange - var objectWillNotChange = new object(); - oldTree.OpenComponent(12); - oldTree.AddAttribute(13, nameof(FakeComponent.StringProperty), "String will change"); - oldTree.AddAttribute(14, nameof(FakeComponent.ObjectProperty), objectWillNotChange); - oldTree.CloseComponent(); - newTree.OpenComponent(12); - newTree.AddAttribute(13, nameof(FakeComponent.StringProperty), "String did change"); - newTree.AddAttribute(14, nameof(FakeComponent.ObjectProperty), objectWillNotChange); - newTree.CloseComponent(); - - using var batchBuilder = new RenderBatchBuilder(); - using var renderTree = new RenderTreeBuilder(); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTree.GetFrames(), oldTree.GetFrames()); - var originalComponentInstance = (FakeComponent)oldTree.GetFrames().Array[0].Component; - - // Act - var renderBatch = GetRenderedBatch(); - var newComponentInstance = (FakeComponent)oldTree.GetFrames().Array[0].Component; - - // Assert - Assert.Equal(1, renderBatch.UpdatedComponents.Count); // Because the diff builder only queues child component renders; it doesn't actually perform them itself - Assert.Same(originalComponentInstance, newComponentInstance); - Assert.Equal("String did change", newComponentInstance.StringProperty); - Assert.Same(objectWillNotChange, newComponentInstance.ObjectProperty); - } - - [Fact] - public void SkipsUpdatingParametersOnChildComponentsIfAllAreDefinitelyImmutableAndUnchanged() - { - // We only know that types are immutable if either Type.IsPrimitive, or it's one of - // a known set of common immutable types. - - // Arrange: Populate old and new with equivalent content - RenderFragment fragmentWillNotChange = builder => throw new NotImplementedException(); - var dateTimeWillNotChange = DateTime.Now; - foreach (var tree in new[] { oldTree, newTree }) - { - tree.OpenComponent(0); - tree.AddAttribute(1, "MyString", "Some fixed string"); - tree.AddAttribute(1, "MyByte", (byte)123); - tree.AddAttribute(1, "MyInt", int.MaxValue); - tree.AddAttribute(1, "MyLong", long.MaxValue); - tree.AddAttribute(1, "MyBool", true); - tree.AddAttribute(1, "MyFloat", float.MaxValue); - tree.AddAttribute(1, "MyDouble", double.MaxValue); - tree.AddAttribute(1, "MyDecimal", decimal.MinusOne); - tree.AddAttribute(1, "MyDate", dateTimeWillNotChange); - tree.CloseComponent(); - } - - using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTreeBuilder.GetFrames(), oldTree.GetFrames()); - var originalComponentInstance = (CaptureSetParametersComponent)oldTree.GetFrames().Array[0].Component; - Assert.Equal(1, originalComponentInstance.SetParametersCallCount); - - // Act - var renderBatch = GetRenderedBatch(); - var newComponentInstance = (CaptureSetParametersComponent)oldTree.GetFrames().Array[0].Component; - - // Assert - Assert.Same(originalComponentInstance, newComponentInstance); - Assert.Equal(1, originalComponentInstance.SetParametersCallCount); // Received no further parameter change notification - } - - [Fact] - public void AlwaysRegardsRenderFragmentAsPossiblyChanged() - { - // Even if the RenderFragment instance itself is unchanged, the output you get - // when invoking it might have changed (they aren't pure functions in general) - - // Arrange: Populate old and new with equivalent content - RenderFragment fragmentWillNotChange = builder => throw new NotImplementedException(); - foreach (var tree in new[] { oldTree, newTree }) - { - tree.OpenComponent(0); - tree.AddAttribute(1, "MyFragment", fragmentWillNotChange); - tree.CloseComponent(); - } - - using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTreeBuilder.GetFrames(), oldTree.GetFrames()); - var componentInstance = (CaptureSetParametersComponent)oldTree.GetFrames().Array[0].Component; - Assert.Equal(1, componentInstance.SetParametersCallCount); - - // Act - var renderBatch = GetRenderedBatch(); - - // Assert - Assert.Equal(2, componentInstance.SetParametersCallCount); - } - - [Fact] - public void QueuesRemovedChildComponentsForDisposal() - { - // Arrange - oldTree.OpenComponent(10); // - oldTree.CloseComponent(); // - oldTree.OpenComponent(20); // - oldTree.CloseComponent(); // - oldTree.OpenComponent(30); // - oldTree.CloseComponent(); // - newTree.OpenComponent(30); // - newTree.CloseComponent(); // - - using var batchBuilder = new RenderBatchBuilder(); - using var renderTree = new RenderTreeBuilder(); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTree.GetFrames(), oldTree.GetFrames()); - - // Act/Assert - // Note that we track NonDisposableComponent was disposed even though it's not IDisposable, - // because it's up to the upstream renderer to decide what "disposing" a component means - Assert.Empty(batchBuilder.ComponentDisposalQueue); - RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, oldTree.GetFrames(), newTree.GetFrames()); - Assert.Equal(new[] { 0, 1 }, batchBuilder.ComponentDisposalQueue); - } - - [Fact] - public void AssignsDistinctIdToNewElementReferenceCaptures() - { - // Arrange - ElementReference ref1 = default, ref2 = default; - Action capture1 = val => { ref1 = val; }; - Action capture2 = val => { ref2 = val; }; - newTree.OpenElement(0, "My element"); - newTree.AddElementReferenceCapture(1, capture1); - newTree.AddElementReferenceCapture(2, capture2); - newTree.CloseElement(); - - // Act - var (diff, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert: Distinct nonnull IDs - Assert.NotNull(ref1.Id); - Assert.NotNull(ref2.Id); - Assert.NotEqual(ref1.Id, ref2.Id); - - // Assert: Also specified in diff - Assert.Collection(diff.Edits, edit => - { - AssertEdit(edit, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - Assert.Collection(referenceFrames, - frame => AssertFrame.Element(frame, "My element", 3), - frame => - { - AssertFrame.ElementReferenceCapture(frame, capture1); - Assert.Equal(ref1.Id, frame.ElementReferenceCaptureId); - }, - frame => - { - AssertFrame.ElementReferenceCapture(frame, capture2); - Assert.Equal(ref2.Id, frame.ElementReferenceCaptureId); - }); - } - - [Fact] - public void PreservesIdsOnRetainedElementReferenceCaptures() - { - // Arrange - var refWriteCount = 0; - ElementReference ref1 = default; - Action capture1 = val => { ref1 = val; refWriteCount++; }; - oldTree.OpenElement(0, "My element"); - oldTree.AddElementReferenceCapture(1, capture1); - oldTree.CloseElement(); - newTree.OpenElement(0, "My element"); - newTree.AddElementReferenceCapture(1, capture1); - newTree.CloseElement(); - - // Act - var (diff, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true); - - // Assert: Did not invoke the capture action a second time - // Note: We're not preserving the ReferenceCaptureId on the actual RenderTreeFrames in the same - // way we do for event handler IDs, simply because there's no need to do so. We only do - // anything with ReferenceCaptureId when frames are first inserted into the document. - Assert.NotNull(ref1.Id); - Assert.Equal(1, refWriteCount); - Assert.Empty(diff.Edits); - Assert.Empty(referenceFrames); - } - - [Fact] - public void InvokesAssignerForComponentReferenceCapturesOnInsertion() - { - // Arrange - FakeComponent capturedInstance1 = null, capturedInstance2 = null; - Action assigner1 = val => { capturedInstance1 = (FakeComponent)val; }; - Action assigner2 = val => { capturedInstance2 = (FakeComponent)val; }; - newTree.OpenComponent(0); - newTree.AddComponentReferenceCapture(1, assigner1); - newTree.AddComponentReferenceCapture(2, assigner2); - newTree.CloseComponent(); - - // Act - var (diff, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert: Assigned references - Assert.NotNull(capturedInstance1); - Assert.NotNull(capturedInstance2); - Assert.IsType(capturedInstance1); - Assert.IsType(capturedInstance2); - Assert.Same(capturedInstance1, capturedInstance2); - - // Assert: Also in diff, even though we have no use for it there - // (it would be costly to exclude given how the array range is copied) - Assert.Collection(diff.Edits, edit => - { - AssertEdit(edit, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - Assert.Collection(referenceFrames, - frame => - { - AssertFrame.Component(frame, 3, 0); - Assert.Same(capturedInstance1, frame.Component); - }, - frame => AssertFrame.ComponentReferenceCapture(frame, assigner1, 1), - frame => AssertFrame.ComponentReferenceCapture(frame, assigner2, 2)); - } - - [Fact] - public void DoesNotInvokeAssignerAgainForRetainedComponents() - { - // Arrange - var refWriteCount = 0; - FakeComponent capturedInstance = null; - Action assigner = val => { capturedInstance = (FakeComponent)val; refWriteCount++; }; - oldTree.OpenComponent(0); - oldTree.AddComponentReferenceCapture(1, assigner); - oldTree.CloseComponent(); - newTree.OpenComponent(0); - newTree.AddComponentReferenceCapture(1, assigner); - newTree.CloseComponent(); - - // Act - var (diff, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true); - - // Assert: Did not invoke the capture action a second time - Assert.NotNull(capturedInstance); - Assert.IsType(capturedInstance); - Assert.Equal(1, refWriteCount); - Assert.Empty(diff.Edits); - Assert.Empty(referenceFrames); - } - - [Fact] - public void RecognizesKeyedElementMoves() - { - // Arrange - oldTree.OpenElement(0, "container"); - oldTree.SetKey("first key"); - oldTree.AddContent(1, "First"); - oldTree.CloseElement(); - - oldTree.AddContent(2, "Unkeyed item"); - - oldTree.OpenElement(0, "container"); - oldTree.SetKey("second key"); - oldTree.AddContent(1, "Second"); - oldTree.CloseElement(); - - newTree.OpenElement(0, "container"); - newTree.SetKey("second key"); - newTree.AddContent(1, "Second"); - newTree.CloseElement(); - - newTree.AddContent(2, "Unkeyed item"); - - newTree.OpenElement(0, "container"); - newTree.SetKey("first key"); - newTree.AddContent(1, "First modified"); - newTree.CloseElement(); - - // Without the key, it changes the text contents of both - // With the key, it reorders them and just updates the text content of one - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - // First we update the modified descendants in place - entry => AssertEdit(entry, RenderTreeEditType.StepIn, 0), - entry => - { - AssertEdit(entry, RenderTreeEditType.UpdateText, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("First modified", referenceFrames[entry.ReferenceFrameIndex].TextContent); - }, - entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0), - - // Then we have the permutation list - entry => AssertPermutationListEntry(entry, 0, 2), - entry => AssertPermutationListEntry(entry, 2, 0), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void RecognizesKeyedComponentMoves() - { - // Arrange - oldTree.OpenComponent(0); - oldTree.SetKey("first key"); - oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "First param"); - oldTree.CloseComponent(); - - oldTree.AddContent(2, "Unkeyed item"); - - oldTree.OpenComponent(0); - oldTree.SetKey("second key"); - oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Second param"); - oldTree.CloseComponent(); - - using var renderTreeBuilder = new RenderTreeBuilder(); - GetRenderedBatch(renderTreeBuilder, oldTree, false); // Assign initial IDs - var oldComponents = GetComponents(oldTree); - - newTree.OpenComponent(0); - newTree.SetKey("second key"); - newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Second param"); - newTree.CloseComponent(); - - newTree.AddContent(2, "Unkeyed item"); - - newTree.OpenComponent(0); - newTree.SetKey("first key"); - newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "First param modified"); - newTree.CloseComponent(); - - // Without the key, it changes the parameter on both - // With the key, it reorders them and just updates the parameter of one - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - var newComponents = GetComponents(newTree); - - // Assert: Retains component instances - Assert.Same(oldComponents[0], newComponents[1]); - Assert.Same(oldComponents[1], newComponents[0]); - - // Assert: Supplies updated params only to (originally) first component - Assert.Equal(2, oldComponents[0].SetParametersCallCount); - Assert.Equal(1, oldComponents[1].SetParametersCallCount); - - // Assert: Correct diff - Assert.Collection(result.Edits, - entry => AssertPermutationListEntry(entry, 0, 2), - entry => AssertPermutationListEntry(entry, 2, 0), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void CanMoveBeforeInsertedItem() - { - // Arrange - AddWithKey(oldTree, "will retain"); - AddWithKey(oldTree, "will move"); - - AddWithKey(newTree, "will move"); - AddWithKey(newTree, "newly inserted"); - AddWithKey(newTree, "will retain"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("newly inserted", referenceFrames[entry.ReferenceFrameIndex].ElementKey); - }, - entry => AssertPermutationListEntry(entry, 0, 2), - entry => AssertPermutationListEntry(entry, 2, 0), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void CanMoveBeforeDeletedItem() - { - // Arrange - AddWithKey(oldTree, "will retain"); - AddWithKey(oldTree, "will delete"); - AddWithKey(oldTree, "will move"); - - AddWithKey(newTree, "will move"); - AddWithKey(newTree, "will retain"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), - entry => AssertPermutationListEntry(entry, 0, 1), - entry => AssertPermutationListEntry(entry, 1, 0), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void CanMoveAfterInsertedItem() - { - // Arrange - AddWithKey(oldTree, "will move"); - AddWithKey(oldTree, "will retain"); - - AddWithKey(newTree, "newly inserted"); - AddWithKey(newTree, "will retain"); - AddWithKey(newTree, "will move"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("newly inserted", referenceFrames[entry.ReferenceFrameIndex].ElementKey); - }, - entry => AssertPermutationListEntry(entry, 1, 2), - entry => AssertPermutationListEntry(entry, 2, 1), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void CanMoveAfterDeletedItem() - { - // Arrange - AddWithKey(oldTree, "will move"); - AddWithKey(oldTree, "will delete"); - AddWithKey(oldTree, "will retain"); - - AddWithKey(newTree, "will retain"); - AddWithKey(newTree, "will move"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), - entry => AssertPermutationListEntry(entry, 0, 1), - entry => AssertPermutationListEntry(entry, 1, 0), - entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); - } - - [Fact] - public void CanChangeFrameTypeWithMatchingSequenceNumber() - { - oldTree.OpenElement(0, "some elem"); - oldTree.AddContent(1, "Hello!"); - oldTree.CloseElement(); - - newTree.AddContent(0, "some text"); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("some text", referenceFrames[entry.ReferenceFrameIndex].TextContent); - }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - [Fact] - public void CanChangeFrameTypeWithMatchingKey() - { - oldTree.OpenComponent(0); - oldTree.CloseComponent(); - - newTree.OpenElement(0, "some elem"); - newTree.SetKey("my key"); - newTree.CloseElement(); - - // Act - var (result, referenceFrames) = GetSingleUpdatedComponent(); - - // Assert - Assert.Collection(result.Edits, - entry => - { - AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); - Assert.Equal(0, entry.ReferenceFrameIndex); - Assert.Equal("some elem", referenceFrames[entry.ReferenceFrameIndex].ElementName); - }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); - } - - private (RenderTreeDiff, RenderTreeFrame[]) GetSingleUpdatedComponent(bool initializeFromFrames = false) - { - var result = GetSingleUpdatedComponentWithBatch(initializeFromFrames); - return (result.Item1, result.Item2); - } - - private (RenderTreeDiff, RenderTreeFrame[], RenderBatch) GetSingleUpdatedComponentWithBatch(bool initializeFromFrames = false) - { - var batch = GetRenderedBatch(initializeFromFrames); - var diffsInBatch = batch.UpdatedComponents; - Assert.Equal(1, diffsInBatch.Count); - return (diffsInBatch.Array[0], batch.ReferenceFrames.AsEnumerable().ToArray(), batch); - } - - private RenderBatch GetRenderedBatch(bool initializeFromFrames = false) - => GetRenderedBatch(oldTree, newTree, initializeFromFrames); - - private RenderBatch GetRenderedBatch(RenderTreeBuilder from, RenderTreeBuilder to, bool initializeFromFrames) - { - if (initializeFromFrames) - { - using var renderTreeBuilder = new RenderTreeBuilder(); - using var initializeBatchBuilder = new RenderBatchBuilder(); - - var emptyFrames = renderTreeBuilder.GetFrames(); - var oldFrames = from.GetFrames(); - - RenderTreeDiffBuilder.ComputeDiff(renderer, initializeBatchBuilder, 0, emptyFrames, oldFrames); - } - - batchBuilder?.Dispose(); - // This gets disposed as part of the test type's Dispose - batchBuilder = new RenderBatchBuilder(); - - var diff = RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, from.GetFrames(), to.GetFrames()); - batchBuilder.UpdatedComponentDiffs.Append(diff); - return batchBuilder.ToBatch(); - } - - private static IList GetComponents(RenderTreeBuilder builder) - => GetComponents(builder); - - private static IList GetComponents(RenderTreeBuilder builder) where T : IComponent - => builder.GetFrames().AsEnumerable() - .Where(x => x.FrameType == RenderTreeFrameType.Component) - .Select(x => (T)x.Component) - .ToList(); - - private static void AddWithKey(RenderTreeBuilder builder, object key, string attributeValue = null) - { - builder.OpenElement(0, "el"); - builder.SetKey(key); - - if (attributeValue != null) - { - builder.AddAttribute(1, "attrib", attributeValue); - } - - builder.CloseElement(); - } - - private class FakeRenderer : Renderer - { - public FakeRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance) - { - } - - public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); - - protected override void HandleException(Exception exception) - => throw new NotImplementedException(); - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - => Task.CompletedTask; - } - - private class FakeComponent : IComponent - { - [Parameter] - public int IntProperty { get; set; } - - [Parameter] - public string StringProperty { get; set; } - - [Parameter] - public object ObjectProperty { get; set; } - - [Parameter] - public string ReadonlyProperty { get; set; } - - [Parameter] - public string PrivateProperty { get; set; } - - public string NonParameterProperty { get; set; } - - public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - return Task.CompletedTask; - } - } - - private class FakeComponent2 : IComponent - { - public void Attach(RenderHandle renderHandle) - { - } - - public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; - } - - private class CaptureSetParametersComponent : IComponent - { - public int SetParametersCallCount { get; private set; } - - public void Attach(RenderHandle renderHandle) - { - } - - public Task SetParametersAsync(ParameterView parameters) - { - SetParametersCallCount++; - return Task.CompletedTask; - } - } - - private class DisposableComponent : IComponent, IDisposable - { - public int DisposalCount { get; private set; } - public void Dispose() => DisposalCount++; - - public void Attach(RenderHandle renderHandle) { } - - public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; - } - - private class NonDisposableComponent : IComponent - { - public void Attach(RenderHandle renderHandle) { } - - public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; - } - - private static void AssertEdit( - RenderTreeEdit edit, - RenderTreeEditType type, - int siblingIndex) - { - Assert.Equal(type, edit.Type); - Assert.Equal(siblingIndex, edit.SiblingIndex); - } - - private static void AssertPermutationListEntry( - RenderTreeEdit edit, - int fromSiblingIndex, - int toSiblingIndex) - { - Assert.Equal(RenderTreeEditType.PermutationListEntry, edit.Type); - Assert.Equal(fromSiblingIndex, edit.SiblingIndex); - Assert.Equal(toSiblingIndex, edit.MoveToSiblingIndex); - } - } -} diff --git a/src/Components/Components/test/RenderTreeUpdaterTest.cs b/src/Components/Components/test/RenderTreeUpdaterTest.cs deleted file mode 100644 index 5011d6fb4a01..000000000000 --- a/src/Components/Components/test/RenderTreeUpdaterTest.cs +++ /dev/null @@ -1,167 +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 Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class RenderTreeUpdaterTest - { - [Fact] - public void IgnoresUnknownEventHandlerId() - { - // Arrange - var valuePropName = "testprop"; - var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.AddAttribute(2, valuePropName, "initial value"); - builder.CloseElement(); - var frames = builder.GetFrames(); - frames.Array[1] = frames.Array[1].WithAttributeEventHandlerId(123); // An unrelated event - - // Act - RenderTreeUpdater.UpdateToMatchClientState(builder, 456, "new value"); - - // Assert - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 3, 0), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 1), - frame => AssertFrame.Attribute(frame, valuePropName, "initial value", 2)); - } - - [Fact] - public void IgnoresUpdatesToAttributesIfUnexpectedValueTypeSupplied() - { - // Currently we only allow the client to supply a string or a bool, since those are the - // only types of values we render onto attributes - - // Arrange - var valuePropName = "testprop"; - var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.AddAttribute(2, valuePropName, "initial value"); - builder.CloseElement(); - var frames = builder.GetFrames(); - frames.Array[1] = frames.Array[1].WithAttributeEventHandlerId(123); // An unrelated event - - // Act - RenderTreeUpdater.UpdateToMatchClientState(builder, 123, new object()); - - // Assert - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 3, 0), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 1), - frame => AssertFrame.Attribute(frame, valuePropName, "initial value", 2)); - } - - [Fact] - public void UpdatesOnlyMatchingAttributeValue() - { - // Arrange - var valuePropName = "testprop"; - var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.AddAttribute(2, valuePropName, "unchanged 1"); - builder.CloseElement(); - builder.OpenElement(3, "elem"); - builder.AddAttribute(4, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.AddAttribute(5, "unrelated prop before", "unchanged 2"); - builder.AddAttribute(6, valuePropName, "initial value"); - builder.AddAttribute(7, "unrelated prop after", "unchanged 3"); - builder.CloseElement(); - var frames = builder.GetFrames(); - frames.Array[1] = frames.Array[1].WithAttributeEventHandlerId(123); // An unrelated event - frames.Array[4] = frames.Array[4].WithAttributeEventHandlerId(456); - - // Act - RenderTreeUpdater.UpdateToMatchClientState(builder, 456, "new value"); - - // Assert - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 3, 0), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 1), - frame => AssertFrame.Attribute(frame, valuePropName, "unchanged 1", 2), - frame => AssertFrame.Element(frame, "elem", 5, 3), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 4), - frame => AssertFrame.Attribute(frame, "unrelated prop before", "unchanged 2", 5), - frame => AssertFrame.Attribute(frame, valuePropName, "new value", 6), - frame => AssertFrame.Attribute(frame, "unrelated prop after", "unchanged 3", 7)); - } - - [Fact] - public void AddsAttributeIfNotFound() - { - // Arrange - var valuePropName = "testprop"; - var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.CloseElement(); - var frames = builder.GetFrames(); - frames.Array[1] = frames.Array[1].WithAttributeEventHandlerId(123); - - // Act - RenderTreeUpdater.UpdateToMatchClientState(builder, 123, "new value"); - frames = builder.GetFrames(); - - // Assert - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 3, 0), - frame => AssertFrame.Attribute(frame, valuePropName, "new value", RenderTreeDiffBuilder.SystemAddedAttributeSequenceNumber), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 1)); - } - - [Fact] - public void ExpandsAllAncestorsWhenAddingAttribute() - { - // Arrange - var valuePropName = "testprop"; - var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "grandparent"); - builder.OpenRegion(1); - builder.OpenElement(2, "sibling before"); // To show that non-ancestors aren't expanded - builder.CloseElement(); - builder.OpenElement(3, "elem with handler"); - builder.AddAttribute(4, "eventname", (Action)(() => { })); - builder.SetUpdatesAttributeName(valuePropName); - builder.CloseElement(); // elem with handler - builder.CloseRegion(); - builder.CloseElement(); // grandparent - var frames = builder.GetFrames(); - frames.Array[4] = frames.Array[4].WithAttributeEventHandlerId(123); - - // Act - RenderTreeUpdater.UpdateToMatchClientState(builder, 123, "new value"); - frames = builder.GetFrames(); - - // Assert - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "grandparent", 6, 0), - frame => AssertFrame.Region(frame, 5, 1), - frame => AssertFrame.Element(frame, "sibling before", 1, 2), - frame => AssertFrame.Element(frame, "elem with handler", 3, 3), - frame => AssertFrame.Attribute(frame, valuePropName, "new value", RenderTreeDiffBuilder.SystemAddedAttributeSequenceNumber), - frame => AssertFrame.Attribute(frame, "eventname", v => Assert.IsType(v), 4)); - } - - private static ArrayRange BuildFrames(params RenderTreeFrame[] frames) - => new ArrayRange(frames, frames.Length); - } -} diff --git a/src/Components/Components/test/RendererTest.cs b/src/Components/Components/test/RendererTest.cs deleted file mode 100644 index d0e2affea238..000000000000 --- a/src/Components/Components/test/RendererTest.cs +++ /dev/null @@ -1,4500 +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.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.Logging.Abstractions; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class RendererTest - { - // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch - // failures. - private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10); - - private const string EventActionsName = nameof(NestedAsyncComponent.EventActions); - private const string WhatToRenderName = nameof(NestedAsyncComponent.WhatToRender); - private const string LogName = nameof(NestedAsyncComponent.Log); - - [Fact] - public void CanRenderTopLevelComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenElement(0, "my element"); - builder.AddContent(1, "some text"); - builder.CloseElement(); - }); - - // Act - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Assert - var batch = renderer.Batches.Single(); - var diff = batch.DiffsByComponentId[componentId].Single(); - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - AssertFrame.Element(batch.ReferenceFrames[0], "my element", 2); - AssertFrame.Text(batch.ReferenceFrames[1], "some text"); - } - - [Fact] - public void CanRenderNestedComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.AddContent(0, "Hello"); - builder.OpenComponent(1); - builder.AddAttribute(2, nameof(MessageComponent.Message), "Nested component output"); - builder.CloseComponent(); - }); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var componentFrame = batch.ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponentId = componentFrame.ComponentId; - var nestedComponentDiff = batch.DiffsByComponentId[nestedComponentId].Single(); - - // We rendered both components - Assert.Equal(2, batch.DiffsByComponentId.Count); - - // The nested component exists - Assert.IsType(componentFrame.Component); - - // The nested component was rendered as part of the batch - Assert.Collection(nestedComponentDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Nested component output"); - }); - } - - [Fact] - public void CanReRenderTopLevelComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new MessageComponent { Message = "Initial message" }; - var componentId = renderer.AssignRootComponentId(component); - - // Act/Assert: first render - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var firstDiff = batch.DiffsByComponentId[componentId].Single(); - Assert.Collection(firstDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - AssertFrame.Text(batch.ReferenceFrames[0], "Initial message"); - }); - - // Act/Assert: second render - component.Message = "Modified message"; - component.TriggerRender(); - var secondBatch = renderer.Batches.Skip(1).Single(); - var secondDiff = secondBatch.DiffsByComponentId[componentId].Single(); - Assert.Collection(secondDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - AssertFrame.Text(secondBatch.ReferenceFrames[0], "Modified message"); - }); - } - - [Fact] - public void CanReRenderNestedComponents() - { - // Arrange: parent component already rendered - var renderer = new TestRenderer(); - var parentComponent = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - parentComponent.TriggerRender(); - var nestedComponentFrame = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponent = (MessageComponent)nestedComponentFrame.Component; - var nestedComponentId = nestedComponentFrame.ComponentId; - - // Assert: initial render - nestedComponent.Message = "Render 1"; - nestedComponent.TriggerRender(); - var batch = renderer.Batches[1]; - var firstDiff = batch.DiffsByComponentId[nestedComponentId].Single(); - Assert.Collection(firstDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - AssertFrame.Text(batch.ReferenceFrames[0], "Render 1"); - }); - - // Act/Assert: re-render - nestedComponent.Message = "Render 2"; - nestedComponent.TriggerRender(); - var secondBatch = renderer.Batches[2]; - var secondDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single(); - Assert.Collection(secondDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - AssertFrame.Text(secondBatch.ReferenceFrames[0], "Render 2"); - }); - } - - [Fact] - public async Task CanRenderAsyncTopLevelComponents() - { - // Arrange - var renderer = new TestRenderer(); - var tcs = new TaskCompletionSource(); - var component = new AsyncComponent(tcs.Task, 5); // Triggers n renders, the first one creating

n

and the n-1 renders asynchronously update the value. - - // Act - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId)); - - // Assert - Assert.False(renderTask.IsCompleted); - tcs.SetResult(0); - await renderTask; - Assert.Equal(5, renderer.Batches.Count); - - // First render - var create = renderer.Batches[0]; - var diff = create.DiffsByComponentId[componentId].Single(); - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - AssertFrame.Element(create.ReferenceFrames[0], "p", 2); - AssertFrame.Text(create.ReferenceFrames[1], "5"); - - // Second render - for (var i = 1; i < 5; i++) - { - - var update = renderer.Batches[i]; - var updateDiff = update.DiffsByComponentId[componentId].Single(); - Assert.Collection(updateDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.StepIn, edit.Type); - }, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - }, - edit => - { - Assert.Equal(RenderTreeEditType.StepOut, edit.Type); - }); - AssertFrame.Text(update.ReferenceFrames[0], (5 - i).ToString()); - } - } - - [Fact] - public async Task CanRenderAsyncNestedComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new NestedAsyncComponent(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [EventActionsName] = new Dictionary> - { - [0] = new List - { - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async: true), - }, - [1] = new List - { - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async: true), - } - }, - [WhatToRenderName] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1 }), - [1] = CreateRenderFactory(Array.Empty()) - }, - [LogName] = log - }))); - - var logForParent = log.Where(l => l.id == 0).ToArray(); - var logForChild = log.Where(l => l.id == 1).ToArray(); - - AssertStream(0, logForParent); - AssertStream(1, logForChild); - } - - [Fact] - public async Task CanRenderAsyncComponentsWithSyncChildComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new NestedAsyncComponent(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [EventActionsName] = new Dictionary> - { - [0] = new List - { - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async: true), - }, - [1] = new List - { - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInitAsyncAsync), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync), - } - }, - [WhatToRenderName] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1 }), - [1] = CreateRenderFactory(Array.Empty()) - }, - [LogName] = log - }))); - - var logForParent = log.Where(l => l.id == 0).ToArray(); - var logForChild = log.Where(l => l.id == 1).ToArray(); - - AssertStream(0, logForParent); - AssertStream(1, logForChild); - } - - [Fact] - public async Task CanRenderAsyncComponentsWithAsyncChildInit() - { - // Arrange - var renderer = new TestRenderer(); - var component = new NestedAsyncComponent(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [EventActionsName] = new Dictionary> - { - [0] = new List - { - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async: true), - }, - [1] = new List - { - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync), - } - }, - [WhatToRenderName] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1 }), - [1] = CreateRenderFactory(Array.Empty()) - }, - [LogName] = log - }))); - - var logForParent = log.Where(l => l.id == 0).ToArray(); - var logForChild = log.Where(l => l.id == 1).ToArray(); - - AssertStream(0, logForParent); - AssertStream(1, logForChild); - } - - [Fact] - public async Task CanRenderAsyncComponentsWithMultipleAsyncChildren() - { - // Arrange - var renderer = new TestRenderer(); - var component = new NestedAsyncComponent(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [EventActionsName] = new Dictionary> - { - [0] = new List - { - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(0, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async: true), - }, - [1] = new List - { - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(1, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async:true), - }, - [2] = new List - { - NestedAsyncComponent.ExecutionAction.On(2, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(2, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(2, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(2, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async:true), - }, - [3] = new List - { - NestedAsyncComponent.ExecutionAction.On(3, NestedAsyncComponent.EventType.OnInit), - NestedAsyncComponent.ExecutionAction.On(3, NestedAsyncComponent.EventType.OnInitAsyncAsync, async:true), - NestedAsyncComponent.ExecutionAction.On(3, NestedAsyncComponent.EventType.OnParametersSet), - NestedAsyncComponent.ExecutionAction.On(3, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync, async:true), - } - }, - [WhatToRenderName] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1, 2 }), - [1] = CreateRenderFactory(new[] { 3 }), - [2] = CreateRenderFactory(Array.Empty()), - [3] = CreateRenderFactory(Array.Empty()) - }, - [LogName] = log - }))); - - var logForParent = log.Where(l => l.id == 0).ToArray(); - var logForFirstChild = log.Where(l => l.id == 1).ToArray(); - var logForSecondChild = log.Where(l => l.id == 2).ToArray(); - var logForThirdChild = log.Where(l => l.id == 3).ToArray(); - - AssertStream(0, logForParent); - AssertStream(1, logForFirstChild); - AssertStream(2, logForSecondChild); - AssertStream(3, logForThirdChild); - } - - [Fact] - public void DispatchingEventsWithoutAsyncWorkShouldCompleteSynchronously() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - EventArgs receivedArgs = null; - - var component = new EventComponent - { - OnTest = args => { receivedArgs = args; } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // This should always be run synchronously - Assert.True(task.IsCompletedSuccessfully); - } - - [Fact] - public void CanDispatchEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - EventArgs receivedArgs = null; - - var component = new EventComponent - { - OnTest = args => { receivedArgs = args; } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Same(eventArgs, receivedArgs); - } - - [Fact] - public void DispatchEventHandlesSynchronousExceptionsFromEventHandlers() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer { - ShouldHandleExceptions = true - }; - - var component = new EventComponent - { - OnTest = args => throw new Exception("Error") - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Empty(renderer.HandledExceptions); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.True(renderTask.IsCompletedSuccessfully); - - var exception = Assert.Single(renderer.HandledExceptions); - Assert.Equal("Error", exception.Message); - } - - [Fact] - public void CanDispatchTypedEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - DerivedEventArgs receivedArgs = null; - - var component = new EventComponent - { - OnClick = args => { receivedArgs = args; } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new DerivedEventArgs(); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Same(eventArgs, receivedArgs); - } - - [Fact] - public void CanDispatchActionEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - object receivedArgs = null; - - var component = new EventComponent - { - OnClickAction = () => { receivedArgs = new object(); } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new DerivedEventArgs(); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.NotNull(receivedArgs); - } - - [Fact] - public void CanDispatchEventsToNestedComponents() - { - EventArgs receivedArgs = null; - - // Arrange: Render parent component - var renderer = new TestRenderer(); - var parentComponent = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - parentComponent.TriggerRender(); - - // Arrange: Render nested component - var nestedComponentFrame = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponent = (EventComponent)nestedComponentFrame.Component; - nestedComponent.OnTest = args => { receivedArgs = args; }; - var nestedComponentId = nestedComponentFrame.ComponentId; - nestedComponent.TriggerRender(); - - // Find nested component's event handler ID - var eventHandlerId = renderer.Batches[1] - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Same(eventArgs, receivedArgs); - } - - [Fact] - public async Task CanAsyncDispatchEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - EventArgs receivedArgs = null; - - var state = 0; - var tcs = new TaskCompletionSource(); - - var component = new EventComponent - { - OnTestAsync = async (args) => - { - receivedArgs = args; - state = 1; - await tcs.Task; - state = 2; - }, - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.Equal(1, state); - Assert.Same(eventArgs, receivedArgs); - - tcs.SetResult(null); - await task; - - Assert.Equal(2, state); - } - - [Fact] - public async Task CanAsyncDispatchTypedEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - DerivedEventArgs receivedArgs = null; - - var state = 0; - var tcs = new TaskCompletionSource(); - - var component = new EventComponent - { - OnClickAsync = async (args) => - { - receivedArgs = args; - state = 1; - await tcs.Task; - state = 2; - } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new DerivedEventArgs(); - var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.Equal(1, state); - Assert.Same(eventArgs, receivedArgs); - - tcs.SetResult(null); - await task; - - Assert.Equal(2, state); - } - - [Fact] - public async Task CanAsyncDispatchActionEventsToTopLevelComponents() - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - object receivedArgs = null; - - var state = 0; - var tcs = new TaskCompletionSource(); - - var component = new EventComponent - { - OnClickAsyncAction = async () => - { - receivedArgs = new object(); - state = 1; - await tcs.Task; - state = 2; - } - }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new DerivedEventArgs(); - var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.Equal(1, state); - Assert.NotNull(receivedArgs); - - tcs.SetResult(null); - await task; - - Assert.Equal(2, state); - } - - [Fact] - public async Task CanAsyncDispatchEventsToNestedComponents() - { - EventArgs receivedArgs = null; - - var state = 0; - var tcs = new TaskCompletionSource(); - - // Arrange: Render parent component - var renderer = new TestRenderer(); - var parentComponent = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - parentComponent.TriggerRender(); - - // Arrange: Render nested component - var nestedComponentFrame = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponent = (EventComponent)nestedComponentFrame.Component; - nestedComponent.OnTestAsync = async (args) => - { - receivedArgs = args; - state = 1; - await tcs.Task; - state = 2; - }; - var nestedComponentId = nestedComponentFrame.ComponentId; - nestedComponent.TriggerRender(); - - // Find nested component's event handler ID - var eventHandlerId = renderer.Batches[1] - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Assert: Event not yet fired - Assert.Null(receivedArgs); - - // Act/Assert: Event can be fired - var eventArgs = new EventArgs(); - var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); - Assert.Equal(1, state); - Assert.Same(eventArgs, receivedArgs); - - tcs.SetResult(null); - await task; - - Assert.Equal(2, state); - } - - // This tests the behaviour of dispatching an event when the event-handler - // delegate is a bound-delegate with a target that points to the parent component. - // - // This is a very common case when a component accepts a delegate parameter that - // will be hooked up to a DOM event handler. It's essential that this will dispatch - // to the parent component so that manual StateHasChanged calls are not necessary. - [Fact] - public async Task EventDispatching_DelegateParameter_MethodToDelegateConversion() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)parentComponent.SomeMethod); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - // This is the inverse case of EventDispatching_DelegateParameter_MethodToDelegateConversion - // where the event-handling delegate has a target that is not a component. - // - // This is a degenerate case that we don't expect to occur in applications often, - // but it's important to verify the semantics. - [Fact] - public async Task EventDispatching_DelegateParameter_NoTargetLambda() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => - { - parentComponent.SomeMethod(); - })); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(0, outerStateChangeCount); - } - - // This is a similar case to EventDispatching_DelegateParameter_MethodToDelegateConversion - // but uses our event handling infrastructure to achieve the same effect. The call to CreateDelegate - // is not necessary for correctness in this case - it should just no op. - [Fact] - public async Task EventDispatching_EventCallback_MethodToDelegateConversion() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Action)parentComponent.SomeMethod)); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - // This is a similar case to EventDispatching_DelegateParameter_NoTargetLambda but it uses - // our event-handling infrastructure to avoid the need for a manual StateHasChanged() - [Fact] - public async Task EventDispatching_EventCallback_NoTargetLambda() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Action)(() => - { - parentComponent.SomeMethod(); - }))); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - // This is a similar case to EventDispatching_DelegateParameter_NoTargetLambda but it uses - // our event-handling infrastructure to avoid the need for a manual StateHasChanged() - [Fact] - public async Task EventDispatching_EventCallback_AsyncNoTargetLambda() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Func)(() => - { - parentComponent.SomeMethod(); - return Task.CompletedTask; - }))); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - [Fact] - public async Task EventDispatching_EventCallbackOfT_MethodToDelegateConversion() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)parentComponent.SomeMethod)); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - // This is a similar case to EventDispatching_DelegateParameter_NoTargetLambda but it uses - // our event-handling infrastructure to avoid the need for a manual StateHasChanged() - [Fact] - public async Task EventDispatching_EventCallbackOfT_NoTargetLambda() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)(() => - { - parentComponent.SomeMethod(); - }))); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - // This is a similar case to EventDispatching_DelegateParameter_NoTargetLambda but it uses - // our event-handling infrastructure to avoid the need for a manual StateHasChanged() - [Fact] - public async Task EventDispatching_EventCallbackOfT_AsyncNoTargetLambda() - { - // Arrange - var outerStateChangeCount = 0; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Func)(() => - { - parentComponent.SomeMethod(); - return Task.CompletedTask; - }))); - builder.CloseComponent(); - }; - parentComponent.OnEvent = () => - { - outerStateChangeCount++; - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var eventArgs = new DerivedEventArgs(); - await renderer.DispatchEventAsync(eventHandlerId, eventArgs); - - // Assert - Assert.Equal(1, parentComponent.SomeMethodCallCount); - Assert.Equal(1, outerStateChangeCount); - } - - [Fact] - public async Task DispatchEventAsync_Delegate_SynchronousCompletion() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => - { - // Do nothing. - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.RanToCompletion, task.Status); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_SynchronousCompletion() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Action)(() => - { - // Do nothing. - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.RanToCompletion, task.Status); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_SynchronousCompletion() - { - // Arrange - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => - { - arg = e; - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.RanToCompletion, task.Status); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_Delegate_SynchronousCancellation() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => - { - throw new OperationCanceledException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_SynchronousCancellation() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Action)(() => - { - throw new OperationCanceledException(); - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_SynchronousCancellation() - { - // Arrange - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => - { - arg = e; - throw new OperationCanceledException(); - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_Delegate_SynchronousException() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => - { - throw new InvalidTimeZoneException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.Faulted, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_SynchronousException() - { - // Arrange - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, (Action)(() => - { - throw new InvalidTimeZoneException(); - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.Faulted, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_SynchronousException() - { - // Arrange - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => - { - arg = e; - throw new InvalidTimeZoneException(); - }))); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.Faulted, task.Status); - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_Delegate_AsynchronousCompletion() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => - { - await tcs.Task; - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_AsynchronousCompletion() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, async () => - { - await tcs.Task; - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_AsynchronousCompletion() - { - // Arrange - var tcs = new TaskCompletionSource(); - - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => - { - arg = e; - await tcs.Task; - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - await task; // Does not throw - } - - [Fact] - public async Task DispatchEventAsync_Delegate_AsynchronousCancellation() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => - { - await tcs.Task; - throw new TaskCanceledException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await task; // Does not throw - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_AsynchronousCancellation() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, async () => - { - await tcs.Task; - throw new TaskCanceledException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await task; // Does not throw - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_AsynchronousCancellation() - { - // Arrange - var tcs = new TaskCompletionSource(); - - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => - { - arg = e; - await tcs.Task; - throw new TaskCanceledException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await task; // Does not throw - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public async Task DispatchEventAsync_Delegate_AsynchronousException() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => - { - await tcs.Task; - throw new InvalidTimeZoneException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclickaction") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallback_AsynchronousException() - { - // Arrange - var tcs = new TaskCompletionSource(); - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallback), EventCallback.Factory.Create(parentComponent, async () => - { - await tcs.Task; - throw new InvalidTimeZoneException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task DispatchEventAsync_EventCallbackOfT_AsynchronousException() - { - // Arrange - var tcs = new TaskCompletionSource(); - - DerivedEventArgs arg = null; - - var renderer = new TestRenderer(); - var parentComponent = new OuterEventComponent(); - parentComponent.RenderFragment = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => - { - arg = e; - await tcs.Task; - throw new InvalidTimeZoneException(); - })); - builder.CloseComponent(); - }; - - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - await parentComponent.TriggerRenderAsync(); - - var eventHandlerId = renderer.Batches[0] - .ReferenceFrames - .First(frame => frame.AttributeName == "onclick") - .AttributeEventHandlerId; - - // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); - - // Assert - Assert.NotNull(arg); - Assert.Equal(TaskStatus.WaitingForActivation, task.Status); - tcs.SetResult(null); - - await Assert.ThrowsAsync(() => task); - } - - [Fact] - public async Task CannotDispatchEventsWithUnknownEventHandlers() - { - // Arrange - var renderer = new TestRenderer(); - - // Act/Assert - await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(0, new EventArgs()); - }); - } - - [Fact] - public void ComponentsCanBeAssociatedWithMultipleRenderers() - { - // Arrange - var renderer1 = new TestRenderer(); - var renderer2 = new TestRenderer(); - var component = new MultiRendererComponent(); - var renderer1ComponentId = renderer1.AssignRootComponentId(component); - renderer2.AssignRootComponentId(new TestComponent(null)); // Just so they don't get the same IDs - var renderer2ComponentId = renderer2.AssignRootComponentId(component); - - // Act/Assert - component.TriggerRender(); - var renderer1Batch = renderer1.Batches.Single(); - var renderer1Diff = renderer1Batch.DiffsByComponentId[renderer1ComponentId].Single(); - Assert.Collection(renderer1Diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text(renderer1Batch.ReferenceFrames[edit.ReferenceFrameIndex], - $"Hello from {nameof(MultiRendererComponent)}", 0); - }); - - var renderer2Batch = renderer2.Batches.Single(); - var renderer2Diff = renderer2Batch.DiffsByComponentId[renderer2ComponentId].Single(); - Assert.Collection(renderer2Diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text(renderer2Batch.ReferenceFrames[edit.ReferenceFrameIndex], - $"Hello from {nameof(MultiRendererComponent)}", 0); - }); - } - - [Fact] - public void PreservesChildComponentInstancesWithNoAttributes() - { - // Arrange: First render, capturing child component instance - var renderer = new TestRenderer(); - var message = "Hello"; - var component = new TestComponent(builder => - { - builder.AddContent(0, message); - builder.OpenComponent(1); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var nestedComponentFrame = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponentInstance = (MessageComponent)nestedComponentFrame.Component; - - // Act: Second render - message = "Modified message"; - component.TriggerRender(); - - // Assert - var batch = renderer.Batches[1]; - var diff = batch.DiffsByComponentId[rootComponentId].Single(); - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - AssertFrame.Text(batch.ReferenceFrames[0], "Modified message"); - Assert.False(batch.DiffsByComponentId.ContainsKey(nestedComponentFrame.ComponentId)); - } - - [Fact] - public void UpdatesPropertiesOnRetainedChildComponentInstances() - { - // Arrange: First render, capturing child component instance - var renderer = new TestRenderer(); - var objectThatWillNotChange = new object(); - var firstRender = true; - var component = new TestComponent(builder => - { - builder.OpenComponent(1); - builder.AddAttribute(2, nameof(FakeComponent.IntProperty), firstRender ? 123 : 256); - builder.AddAttribute(3, nameof(FakeComponent.ObjectProperty), objectThatWillNotChange); - builder.AddAttribute(4, nameof(FakeComponent.StringProperty), firstRender ? "String that will change" : "String that did change"); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var originalComponentFrame = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var childComponentInstance = (FakeComponent)originalComponentFrame.Component; - - // Assert 1: properties were assigned - Assert.Equal(123, childComponentInstance.IntProperty); - Assert.Equal("String that will change", childComponentInstance.StringProperty); - Assert.Same(objectThatWillNotChange, childComponentInstance.ObjectProperty); - - // Act: Second render - firstRender = false; - component.TriggerRender(); - - // Assert - Assert.Equal(256, childComponentInstance.IntProperty); - Assert.Equal("String that did change", childComponentInstance.StringProperty); - Assert.Same(objectThatWillNotChange, childComponentInstance.ObjectProperty); - } - - [Fact] - public void ReRendersChildComponentsWhenPropertiesChange() - { - // Arrange: First render - var renderer = new TestRenderer(); - var firstRender = true; - var component = new TestComponent(builder => - { - builder.OpenComponent(1); - builder.AddAttribute(2, nameof(MessageComponent.Message), firstRender ? "first" : "second"); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var childComponentId = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component) - .ComponentId; - - // Act: Second render - firstRender = false; - component.TriggerRender(); - var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single(); - - // Assert - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - AssertFrame.Text(renderer.Batches[1].ReferenceFrames[0], "second"); - } - - [Fact] - public void ReRendersChildComponentWhenUnmatchedValuesChange() - { - // Arrange: First render - var renderer = new TestRenderer(); - var firstRender = true; - var component = new TestComponent(builder => - { - builder.OpenComponent(1); - builder.AddAttribute(1, "class", firstRender ? "first" : "second"); - builder.AddAttribute(2, "id", "some_text"); - builder.AddAttribute(3, nameof(MyStrongComponent.Text), "hi there."); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var childComponentId = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component) - .ComponentId; - - // Act: Second render - firstRender = false; - component.TriggerRender(); - var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single(); - - // Assert - Assert.Collection(diff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.SetAttribute, edit.Type); - Assert.Equal(0, edit.ReferenceFrameIndex); - }); - AssertFrame.Attribute(renderer.Batches[1].ReferenceFrames[0], "class", "second"); - } - - // This is a sanity check that diffs of "unmatched" values *just work* without any specialized - // code in the renderer to handle it. All of the data that's used in the diff is contained in - // the render tree, and the diff process does not need to inspect the state of the component. - [Fact] - public void ReRendersDoesNotReRenderChildComponentWhenUnmatchedValuesDoNotChange() - { - // Arrange: First render - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.OpenComponent(1); - builder.AddAttribute(1, "class", "cool-beans"); - builder.AddAttribute(2, "id", "some_text"); - builder.AddAttribute(3, nameof(MyStrongComponent.Text), "hi there."); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var childComponentId = renderer.Batches.Single() - .ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component) - .ComponentId; - - // Act: Second render - component.TriggerRender(); - - // Assert - Assert.False(renderer.Batches[1].DiffsByComponentId.ContainsKey(childComponentId)); - } - - [Fact] - public void RenderBatchIncludesListOfDisposedComponents() - { - // Arrange - var renderer = new TestRenderer(); - var firstRender = true; - var component = new TestComponent(builder => - { - if (firstRender) - { - // Nested descendants - builder.OpenComponent>(100); - builder.AddAttribute(101, nameof(ConditionalParentComponent.IncludeChild), true); - builder.CloseComponent(); - } - builder.OpenComponent(200); - builder.CloseComponent(); - }); - - var rootComponentId = renderer.AssignRootComponentId(component); - - // Act/Assert 1: First render, capturing child component IDs - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single(); - var childComponentIds = rootComponentDiff - .Edits - .Select(edit => batch.ReferenceFrames[edit.ReferenceFrameIndex]) - .Where(frame => frame.FrameType == RenderTreeFrameType.Component) - .Select(frame => frame.ComponentId) - .ToList(); - var childComponent3 = batch.ReferenceFrames.Where(f => f.ComponentId == 3) - .Single().Component; - Assert.Equal(new[] { 1, 2 }, childComponentIds); - Assert.IsType(childComponent3); - - // Act: Second render - firstRender = false; - component.TriggerRender(); - - // Assert: Applicable children are included in disposal list - Assert.Equal(2, renderer.Batches.Count); - Assert.Equal(new[] { 1, 3 }, renderer.Batches[1].DisposedComponentIDs); - - // Act/Assert: If a disposed component requests a render, it's a no-op - var renderHandle = ((FakeComponent)childComponent3).RenderHandle; - renderHandle.Dispatcher.InvokeAsync(() => renderHandle.Render(builder - => throw new NotImplementedException("Should not be invoked"))); - Assert.Equal(2, renderer.Batches.Count); - } - - [Fact] - public void RenderBatch_HandlesExceptionsFromAllDisposedComponents() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var exception1 = new Exception(); - var exception2 = new Exception(); - - var firstRender = true; - var component = new TestComponent(builder => - { - if (firstRender) - { - builder.AddContent(0, "Hello"); - builder.OpenComponent(1); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => throw exception1)); - builder.CloseComponent(); - - builder.OpenComponent(2); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => throw exception2)); - builder.CloseComponent(); - } - }); - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Act: Second render - firstRender = false; - component.TriggerRender(); - - // Assert: Applicable children are included in disposal list - Assert.Equal(2, renderer.Batches.Count); - Assert.Equal(new[] { 1, 2 }, renderer.Batches[1].DisposedComponentIDs); - - // Outer component is still alive and not disposed. - Assert.False(component.Disposed); - var aex = Assert.IsType(Assert.Single(renderer.HandledExceptions)); - Assert.Contains(exception1, aex.InnerExceptions); - Assert.Contains(exception2, aex.InnerExceptions); - } - - [Fact] - public void RenderBatch_DoesNotDisposeComponentMultipleTimes() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var exception1 = new Exception(); - var exception2 = new Exception(); - - var count1 = 0; - var count2 = 0; - var count3 = 0; - var count4 = 0; - var count5 = 0; - - var firstRender = true; - var component = new TestComponent(builder => - { - if (firstRender) - { - builder.AddContent(0, "Hello"); - builder.OpenComponent(1); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => { count1++; })); - builder.CloseComponent(); - - builder.OpenComponent(2); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => { count2++; throw exception1; })); - builder.CloseComponent(); - - builder.OpenComponent(3); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => { count3++; })); - builder.CloseComponent(); - } - - builder.OpenComponent(4); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => { count4++; throw exception2; })); - builder.CloseComponent(); - - builder.OpenComponent(5); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => { count5++; })); - builder.CloseComponent(); - }); - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Act: Second render - firstRender = false; - component.TriggerRender(); - - // Assert: Applicable children are included in disposal list - Assert.Equal(2, renderer.Batches.Count); - Assert.Equal(new[] { 1, 2, 3 }, renderer.Batches[1].DisposedComponentIDs); - - // Components "disposed" in the batch were all disposed, components that are still live were not disposed - Assert.Equal(1, count1); - Assert.Equal(1, count2); - Assert.Equal(1, count3); - Assert.Equal(0, count4); - Assert.Equal(0, count5); - - // Outer component is still alive and not disposed. - Assert.False(component.Disposed); - var ex = Assert.IsType(Assert.Single(renderer.HandledExceptions)); - Assert.Same(exception1, ex); - - // Act: Dispose renderer - renderer.Dispose(); - - Assert.Equal(2, renderer.HandledExceptions.Count); - ex = renderer.HandledExceptions[1]; - Assert.Same(exception2, ex); - - // Assert: Everything was disposed once. - Assert.Equal(1, count1); - Assert.Equal(1, count2); - Assert.Equal(1, count3); - Assert.Equal(1, count4); - Assert.Equal(1, count5); - Assert.True(component.Disposed); - } - - [Fact] - public async Task DisposesEventHandlersWhenAttributeValueChanged() - { - // Arrange - var renderer = new TestRenderer(); - var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; - var component = new EventComponent { OnTest = origEventHandler }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var origEventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Attribute) - .Single(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act/Assert 1: Event handler fires when we trigger it - Assert.Equal(0, eventCount); - var renderTask = renderer.DispatchEventAsync(origEventHandlerId, args: null); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(1, eventCount); - await renderTask; - - // Now change the attribute value - var newEventCount = 0; - component.OnTest = args => { newEventCount++; }; - component.TriggerRender(); - - // Act/Assert 2: Can no longer fire the original event, but can fire the new event - await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(origEventHandlerId, args: null); - }); - - Assert.Equal(1, eventCount); - Assert.Equal(0, newEventCount); - renderTask = renderer.DispatchEventAsync(origEventHandlerId + 1, args: null); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(1, newEventCount); - await renderTask; - } - - [Fact] - public async Task DisposesEventHandlersWhenAttributeRemoved() - { - // Arrange - var renderer = new TestRenderer(); - var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; - var component = new EventComponent { OnTest = origEventHandler }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var origEventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Attribute) - .Single(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act/Assert 1: Event handler fires when we trigger it - Assert.Equal(0, eventCount); - var renderTask = renderer.DispatchEventAsync(origEventHandlerId, args: null); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(1, eventCount); - await renderTask; - - // Now remove the event attribute - component.OnTest = null; - component.TriggerRender(); - - // Act/Assert 2: Can no longer fire the original event - await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(origEventHandlerId, args: null); - }); - Assert.Equal(1, eventCount); - } - - [Fact] - public async Task DisposesEventHandlersWhenOwnerComponentRemoved() - { - // Arrange - var renderer = new TestRenderer(); - var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; - var component = new ConditionalParentComponent - { - IncludeChild = true, - ChildParameters = new Dictionary - { - { nameof(EventComponent.OnTest), origEventHandler } - } - }; - var rootComponentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single(); - var rootComponentFrame = batch.ReferenceFrames[0]; - var childComponentFrame = rootComponentDiff.Edits - .Select(e => batch.ReferenceFrames[e.ReferenceFrameIndex]) - .Where(f => f.FrameType == RenderTreeFrameType.Component) - .Single(); - var childComponentId = childComponentFrame.ComponentId; - var childComponentDiff = batch.DiffsByComponentId[childComponentFrame.ComponentId].Single(); - var eventHandlerId = batch.ReferenceFrames - .Skip(childComponentDiff.Edits[0].ReferenceFrameIndex) // Search from where the child component frames start - .Where(f => f.FrameType == RenderTreeFrameType.Attribute) - .Single(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act/Assert 1: Event handler fires when we trigger it - Assert.Equal(0, eventCount); - var renderTask = renderer.DispatchEventAsync(eventHandlerId, args: null); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(1, eventCount); - await renderTask; - - // Now remove the EventComponent - component.IncludeChild = false; - component.TriggerRender(); - - // Act/Assert 2: Can no longer fire the original event - await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(eventHandlerId, args: null); - }); - Assert.Equal(1, eventCount); - } - - [Fact] - public async Task DisposesEventHandlersWhenAncestorElementRemoved() - { - // Arrange - var renderer = new TestRenderer(); - var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; - var component = new EventComponent { OnTest = origEventHandler }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var origEventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Attribute) - .Single(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act/Assert 1: Event handler fires when we trigger it - Assert.Equal(0, eventCount); - var renderTask = renderer.DispatchEventAsync(origEventHandlerId, args: null); - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(1, eventCount); - await renderTask; - - // Now remove the ancestor element - component.SkipElement = true; - component.TriggerRender(); - - // Act/Assert 2: Can no longer fire the original event - await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(origEventHandlerId, args: null); - }); - Assert.Equal(1, eventCount); - } - - [Fact] - public async Task AllRendersTriggeredSynchronouslyDuringEventHandlerAreHandledAsSingleBatch() - { - // Arrange: A root component with a child whose event handler explicitly queues - // a re-render of both the root component and the child - var renderer = new TestRenderer(); - var eventCount = 0; - TestComponent rootComponent = null; - EventComponent childComponent = null; - rootComponent = new TestComponent(builder => - { - builder.AddContent(0, "Child event count: " + eventCount); - builder.OpenComponent(1); - builder.AddAttribute(2, nameof(EventComponent.OnTest), new Action(args => - { - eventCount++; - rootComponent.TriggerRender(); - childComponent.TriggerRender(); - })); - builder.CloseComponent(); - }); - var rootComponentId = renderer.AssignRootComponentId(rootComponent); - rootComponent.TriggerRender(); - var origBatchReferenceFrames = renderer.Batches.Single().ReferenceFrames; - var childComponentFrame = origBatchReferenceFrames - .Single(f => f.Component is EventComponent); - var childComponentId = childComponentFrame.ComponentId; - childComponent = (EventComponent)childComponentFrame.Component; - var origEventHandlerId = origBatchReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Attribute) - .Last(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - Assert.Single(renderer.Batches); - - // Act - var renderTask = renderer.DispatchEventAsync(origEventHandlerId, args: null); - - // Assert - Assert.True(renderTask.IsCompletedSuccessfully); - await renderTask; - - Assert.Equal(2, renderer.Batches.Count); - var batch = renderer.Batches.Last(); - Assert.Collection(batch.DiffsInOrder, - diff => - { - // First we triggered the root component to re-render - Assert.Equal(rootComponentId, diff.ComponentId); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Child event count: 1"); - }); - }, - diff => - { - // Then the root re-render will have triggered an update to the child - Assert.Equal(childComponentId, diff.ComponentId); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Render count: 2"); - }); - }, - diff => - { - // Finally we explicitly requested a re-render of the child - Assert.Equal(childComponentId, diff.ComponentId); - Assert.Collection(diff.Edits, edit => - { - Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Render count: 3"); - }); - }); - } - - [Fact] - public void ComponentCannotTriggerRenderBeforeRenderHandleAssigned() - { - // Arrange - var component = new TestComponent(builder => { }); - - // Act/Assert - var ex = Assert.Throws(() => component.TriggerRender()); - Assert.Equal("The render handle is not yet assigned.", ex.Message); - } - - [Fact] - public void ComponentCanTriggerRenderWhenNoBatchIsInProgress() - { - // Arrange - var renderer = new TestRenderer(); - var renderCount = 0; - var component = new TestComponent(builder => - { - builder.AddContent(0, $"Render count: {++renderCount}"); - }); - var componentId = renderer.AssignRootComponentId(component); - - // Act/Assert: Can trigger initial render - Assert.Equal(0, renderCount); - component.TriggerRender(); - Assert.Equal(1, renderCount); - var batch1 = renderer.Batches.Single(); - var edit1 = batch1.DiffsByComponentId[componentId].Single().Edits.Single(); - Assert.Equal(RenderTreeEditType.PrependFrame, edit1.Type); - AssertFrame.Text(batch1.ReferenceFrames[edit1.ReferenceFrameIndex], - "Render count: 1", 0); - - // Act/Assert: Can trigger subsequent render - component.TriggerRender(); - Assert.Equal(2, renderCount); - var batch2 = renderer.Batches.Skip(1).Single(); - var edit2 = batch2.DiffsByComponentId[componentId].Single().Edits.Single(); - Assert.Equal(RenderTreeEditType.UpdateText, edit2.Type); - AssertFrame.Text(batch2.ReferenceFrames[edit2.ReferenceFrameIndex], - "Render count: 2", 0); - } - - [Fact] - public void ComponentCanTriggerRenderWhenExistingBatchIsInProgress() - { - // Arrange - var renderer = new TestRenderer(); - TestComponent parent = null; - var parentRenderCount = 0; - parent = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(ReRendersParentComponent.Parent), parent); - builder.CloseComponent(); - builder.AddContent(2, $"Parent render count: {++parentRenderCount}"); - }); - var parentComponentId = renderer.AssignRootComponentId(parent); - - // Act - parent.TriggerRender(); - - // Assert - var batch = renderer.Batches.Single(); - Assert.Equal(4, batch.DiffsInOrder.Count); - - // First is the parent component's initial render - var diff1 = batch.DiffsInOrder[0]; - Assert.Equal(parentComponentId, diff1.ComponentId); - Assert.Collection(diff1.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Component( - batch.ReferenceFrames[edit.ReferenceFrameIndex]); - }, - edit => - { - Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); - AssertFrame.Text( - batch.ReferenceFrames[edit.ReferenceFrameIndex], - "Parent render count: 1"); - }); - - // Second is the child component's single render - var diff2 = batch.DiffsInOrder[1]; - Assert.NotEqual(parentComponentId, diff2.ComponentId); - var diff2edit = diff2.Edits.Single(); - Assert.Equal(RenderTreeEditType.PrependFrame, diff2edit.Type); - AssertFrame.Text(batch.ReferenceFrames[diff2edit.ReferenceFrameIndex], - "Child is here"); - - // Third is the parent's triggered render - var diff3 = batch.DiffsInOrder[2]; - Assert.Equal(parentComponentId, diff3.ComponentId); - var diff3edit = diff3.Edits.Single(); - Assert.Equal(RenderTreeEditType.UpdateText, diff3edit.Type); - AssertFrame.Text(batch.ReferenceFrames[diff3edit.ReferenceFrameIndex], - "Parent render count: 2"); - - // Fourth is child's rerender due to parent rendering - var diff4 = batch.DiffsInOrder[3]; - Assert.NotEqual(parentComponentId, diff4.ComponentId); - Assert.Empty(diff4.Edits); - } - - [Fact] - public void QueuedRenderIsSkippedIfComponentWasAlreadyDisposedInSameBatch() - { - // Arrange - var renderer = new TestRenderer(); - var shouldRenderChild = true; - TestComponent component = null; - component = new TestComponent(builder => - { - builder.AddContent(0, "Some frame so the child isn't at position zero"); - if (shouldRenderChild) - { - builder.OpenComponent(1); - builder.AddAttribute(2, "onclick", (Action)((object obj) => - { - // First we queue (1) a re-render of the root component, then the child component - // will queue (2) its own re-render. But by the time (1) completes, the child will - // have been disposed, even though (2) is still in the queue - shouldRenderChild = false; - component.TriggerRender(); - })); - builder.CloseComponent(); - } - }); - - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var childComponentId = renderer.Batches.Single() - .ReferenceFrames - .Where(f => f.ComponentId != 0) - .Single() - .ComponentId; - var origEventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .Where(f => f.FrameType == RenderTreeFrameType.Attribute && f.AttributeName == "onmycustomevent") - .Single(f => f.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act - // The fact that there's no error here is the main thing we're testing - var renderTask = renderer.DispatchEventAsync(origEventHandlerId, args: null); - - // Assert: correct render result - Assert.True(renderTask.IsCompletedSuccessfully); - var newBatch = renderer.Batches.Skip(1).Single(); - Assert.Equal(1, newBatch.DisposedComponentIDs.Count); - Assert.Equal(1, newBatch.DiffsByComponentId.Count); - Assert.Collection(newBatch.DiffsByComponentId[componentId].Single().Edits, - edit => - { - Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type); - Assert.Equal(1, edit.SiblingIndex); - }); - } - - [Fact] - public async Task CanCombineBindAndConditionalAttribute() - { - // This test represents https://github.com/aspnet/Blazor/issues/624 - - // Arrange: Rendered with textbox enabled - var renderer = new TestRenderer(); - var component = new BindPlusConditionalAttributeComponent(); - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var checkboxChangeEventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.FrameType == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerId != 0) - .AttributeEventHandlerId; - - // Act: Toggle the checkbox - var eventArgs = new ChangeEventArgs { Value = true }; - var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs); - - Assert.True(renderTask.IsCompletedSuccessfully); - var latestBatch = renderer.Batches.Last(); - var latestDiff = latestBatch.DiffsInOrder.Single(); - var referenceFrames = latestBatch.ReferenceFrames; - - // Assert: Textbox's "disabled" attribute was removed - Assert.Equal(2, renderer.Batches.Count); - Assert.Equal(componentId, latestDiff.ComponentId); - Assert.Contains(latestDiff.Edits, edit => - edit.SiblingIndex == 1 - && edit.RemovedAttributeName == "disabled"); - - await renderTask; - } - - [Fact] - public void HandlesNestedElementCapturesDuringRefresh() - { - // This may seem like a very arbitrary test case, but at once stage there was a bug - // whereby the diff output was incorrect given a ref capture on an element whose - // parent element also had a ref capture - - // Arrange - var attrValue = 0; - var component = new TestComponent(builder => - { - builder.OpenElement(0, "parent elem"); - builder.AddAttribute(1, "parent elem attr", attrValue); - builder.AddElementReferenceCapture(2, _ => { }); - builder.OpenElement(3, "child elem"); - builder.AddElementReferenceCapture(4, _ => { }); - builder.AddContent(5, "child text"); - builder.CloseElement(); - builder.CloseElement(); - }); - var renderer = new TestRenderer(); - renderer.AssignRootComponentId(component); - - // Act: Update the attribute value on the parent - component.TriggerRender(); - attrValue++; - component.TriggerRender(); - - // Assert - var latestBatch = renderer.Batches.Skip(1).Single(); - var latestDiff = latestBatch.DiffsInOrder.Single(); - Assert.Collection(latestDiff.Edits, - edit => - { - Assert.Equal(RenderTreeEditType.SetAttribute, edit.Type); - Assert.Equal(0, edit.SiblingIndex); - AssertFrame.Attribute(latestBatch.ReferenceFrames[edit.ReferenceFrameIndex], - "parent elem attr", 1); - }); - } - - [Fact] - public void CallsAfterRenderOnEachRender() - { - // Arrange - var onAfterRenderCallCountLog = new List(); - var component = new AfterRenderCaptureComponent(); - var renderer = new TestRenderer - { - OnUpdateDisplay = _ => onAfterRenderCallCountLog.Add(component.OnAfterRenderCallCount) - }; - renderer.AssignRootComponentId(component); - - // Act - component.TriggerRender(); - - // Assert - // When the display was first updated, OnAfterRender had not yet been called - Assert.Equal(new[] { 0 }, onAfterRenderCallCountLog); - // But OnAfterRender was called since then - Assert.Equal(1, component.OnAfterRenderCallCount); - - // Act/Assert 2: On a subsequent render, the same happens again - component.TriggerRender(); - Assert.Equal(new[] { 0, 1 }, onAfterRenderCallCountLog); - Assert.Equal(2, component.OnAfterRenderCallCount); - } - - [Fact] - public void CallsAfterRenderAfterTheUIHasFinishedUpdatingAsynchronously() - { - // Arrange - var @event = new ManualResetEventSlim(); - var tcs = new TaskCompletionSource(); - var afterRenderTcs = new TaskCompletionSource(); - var onAfterRenderCallCountLog = new List(); - var component = new AsyncAfterRenderComponent(afterRenderTcs.Task) - { - OnAfterRenderComplete = () => @event.Set(), - }; - var renderer = new AsyncUpdateTestRenderer() - { - OnUpdateDisplayAsync = _ => tcs.Task, - }; - renderer.AssignRootComponentId(component); - - // Act - component.TriggerRender(); - tcs.SetResult(null); - afterRenderTcs.SetResult(null); - - // We need to wait here because the completions from SetResult will be scheduled. - @event.Wait(Timeout); - - // Assert - Assert.True(component.Called); - } - - [Fact] - public void CallsAfterRenderAfterTheUIHasFinishedUpdatingSynchronously() - { - // Arrange - var @event = new ManualResetEventSlim(); - var afterRenderTcs = new TaskCompletionSource(); - var onAfterRenderCallCountLog = new List(); - var component = new AsyncAfterRenderComponent(afterRenderTcs.Task) - { - OnAfterRenderComplete = () => @event.Set(), - }; - var renderer = new AsyncUpdateTestRenderer() - { - OnUpdateDisplayAsync = _ => Task.CompletedTask - }; - renderer.AssignRootComponentId(component); - - // Act - component.TriggerRender(); - afterRenderTcs.SetResult(null); - - // We need to wait here because the completions from SetResult will be scheduled. - @event.Wait(Timeout); - - // Assert - Assert.True(component.Called); - } - - [Fact] - public void DoesNotCallOnAfterRenderForComponentsNotRendered() - { - // Arrange - var showComponent3 = true; - var parentComponent = new TestComponent(builder => - { - // First child will be re-rendered because we'll change its param - builder.OpenComponent(0); - builder.AddAttribute(1, "some param", showComponent3); - builder.CloseComponent(); - - // Second child will not be re-rendered because nothing changes - builder.OpenComponent(2); - builder.CloseComponent(); - - // Third component will be disposed - if (showComponent3) - { - builder.OpenComponent(3); - builder.CloseComponent(); - } - }); - var renderer = new TestRenderer(); - var parentComponentId = renderer.AssignRootComponentId(parentComponent); - - // Act: First render - parentComponent.TriggerRender(); - - // Assert: All child components were notified of "after render" - var batch1 = renderer.Batches.Single(); - var parentComponentEdits1 = batch1.DiffsByComponentId[parentComponentId].Single().Edits; - var childComponents = parentComponentEdits1 - .Select( - edit => (AfterRenderCaptureComponent)batch1.ReferenceFrames[edit.ReferenceFrameIndex].Component) - .ToArray(); - Assert.Equal(1, childComponents[0].OnAfterRenderCallCount); - Assert.Equal(1, childComponents[1].OnAfterRenderCallCount); - Assert.Equal(1, childComponents[2].OnAfterRenderCallCount); - - // Act: Second render - showComponent3 = false; - parentComponent.TriggerRender(); - - // Assert: Only the re-rendered component was notified of "after render" - var batch2 = renderer.Batches.Skip(1).Single(); - Assert.Equal(2, batch2.DiffsInOrder.Count); // Parent and first child - Assert.Equal(1, batch2.DisposedComponentIDs.Count); // Third child - Assert.Equal(2, childComponents[0].OnAfterRenderCallCount); // Retained and re-rendered - Assert.Equal(1, childComponents[1].OnAfterRenderCallCount); // Retained and not re-rendered - Assert.Equal(1, childComponents[2].OnAfterRenderCallCount); // Disposed - } - - [Fact] - public void CanTriggerRenderingSynchronouslyFromInsideAfterRenderCallback() - { - // Arrange - AfterRenderCaptureComponent component = null; - component = new AfterRenderCaptureComponent - { - OnAfterRenderLogic = () => - { - if (component.OnAfterRenderCallCount < 10) - { - component.TriggerRender(); - } - } - }; - var renderer = new TestRenderer(); - renderer.AssignRootComponentId(component); - - // Act - component.TriggerRender(); - - // Assert - Assert.Equal(10, component.OnAfterRenderCallCount); - } - - [ConditionalFact] - [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/7487")] - public async Task CanTriggerEventHandlerDisposedInEarlierPendingBatchAsync() - { - // This represents the scenario where the same event handler is being triggered - // rapidly, such as an input event while typing. It only applies to asynchronous - // batch updates, i.e., server-side Components. - // Sequence: - // 1. The client dispatches event X twice (say) in quick succession - // 2. The server receives the first instance, handles the event, and re-renders - // some component. The act of re-rendering causes the old event handler to be - // replaced by a new one, so the old one is flagged to be disposed. - // 3. The server receives the second instance. Even though the corresponding event - // handler is flagged to be disposed, we have to still be able to find and - // execute it without errors. - - // Arrange - var renderer = new TestAsyncRenderer - { - NextUpdateDisplayReturnTask = Task.CompletedTask - }; - var numEventsFired = 0; - EventComponent component = null; - Action eventHandler = null; - - eventHandler = _ => - { - numEventsFired++; - - // Replace the old event handler with a different one, - // (old the old handler ID will be disposed) then re-render. - component.OnTest = args => eventHandler(args); - component.TriggerRender(); - }; - - component = new EventComponent { OnTest = eventHandler }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.AttributeValue != null) - .AttributeEventHandlerId; - - // Act/Assert 1: Event can be fired for the first time - var render1TCS = new TaskCompletionSource(); - renderer.NextUpdateDisplayReturnTask = render1TCS.Task; - await renderer.DispatchEventAsync(eventHandlerId, new EventArgs()); - Assert.Equal(1, numEventsFired); - - // Act/Assert 2: *Same* event handler ID can be reused prior to completion of - // preceding UI update - var render2TCS = new TaskCompletionSource(); - renderer.NextUpdateDisplayReturnTask = render2TCS.Task; - await renderer.DispatchEventAsync(eventHandlerId, new EventArgs()); - Assert.Equal(2, numEventsFired); - - // Act/Assert 3: After we complete the first UI update in which a given - // event handler ID is disposed, we can no longer reuse that event handler ID - - // From here we can't see when the async disposal is completed. Just give it plenty of time (Task.Yield isn't enough). - // There is a small chance in which the continuations from TaskCompletionSource run asynchronously. - // In that case we might not be able to see the results from RemoveEventHandlerIds as they might run asynchronously. - // For that case, we are going to queue a continuation on render1TCS.Task, include a 1s delay and await the resulting - // task to offer the best chance that we get to see the error in all cases. - var awaitableTask = render1TCS.Task.ContinueWith(_ => Task.Delay(1000)).Unwrap(); - render1TCS.SetResult(null); - await awaitableTask; - var ex = await Assert.ThrowsAsync(() => - { - return renderer.DispatchEventAsync(eventHandlerId, new EventArgs()); - }); - Assert.Contains($"There is no event handler associated with this event. EventId: '{eventHandlerId}'.", ex.Message); - Assert.Equal(2, numEventsFired); - } - - [Fact] - public void ExceptionsThrownSynchronouslyCanBeHandledSynchronously() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception = new InvalidTimeZoneException(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var task = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = () => throw exception, - }, - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(task.IsCompletedSuccessfully); - Assert.Equal(new[] { exception }, renderer.HandledExceptions); - } - - [Fact] - public void ExceptionsThrownSynchronouslyCanBeHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception = new InvalidTimeZoneException(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = () => throw exception, - }, - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(new[] { exception }, renderer.HandledExceptions); - } - - [Fact] - public void ExceptionsReturnedUsingTaskFromExceptionCanBeHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception = new InvalidTimeZoneException(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = () => Task.FromException<(int, NestedAsyncComponent.EventType)>(exception), - }, - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Equal(new[] { exception }, renderer.HandledExceptions); - } - - [Fact] - public async Task ExceptionsThrownAsynchronouslyDuringFirstRenderCanBeHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var tcs = new TaskCompletionSource(); - var exception = new InvalidTimeZoneException(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = async () => - { - await tcs.Task; - throw exception; - } - }, - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.False(renderTask.IsCompleted); - tcs.SetResult(0); - await renderTask; - Assert.Same(exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - [Fact] - public async Task ExceptionsThrownAsynchronouslyAfterFirstRenderCanBeHandled() - { - // This differs from the "during first render" case, because some aspects of the rendering - // code paths are special cased for the first render because of prerendering. - - // Arrange - var @event = new ManualResetEventSlim(); - var renderer = new TestRenderer() - { - ShouldHandleExceptions = true, - OnExceptionHandled = () => { @event.Set(); }, - }; - var taskToAwait = Task.CompletedTask; - var component = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(ComponentThatAwaitsTask.TaskToAwait), taskToAwait); - builder.CloseComponent(); - }); - var componentId = renderer.AssignRootComponentId(component); - await renderer.RenderRootComponentAsync(componentId); // Not throwing on first render - - var asyncExceptionTcs = new TaskCompletionSource(); - taskToAwait = asyncExceptionTcs.Task; - await renderer.Dispatcher.InvokeAsync(component.TriggerRender); - - // Act - var exception = new InvalidOperationException(); - - @event.Reset(); - asyncExceptionTcs.SetException(exception); - - // We need to wait here because the continuations of SetException will be scheduled to run asynchronously. - @event.Wait(Timeout); - - // Assert - Assert.Same(exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - [Fact] - public async Task ExceptionsThrownAsynchronouslyFromMultipleComponentsCanBeHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception1 = new InvalidTimeZoneException(); - var exception2 = new UriFormatException(); - var tcs = new TaskCompletionSource(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = Array.Empty(), - [1] = new List - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = async () => - { - await tcs.Task; - throw exception1; - } - }, - }, - [2] = new List - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = async () => - { - await tcs.Task; - throw exception2; - } - }, - }, - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1, 2, }), - [1] = CreateRenderFactory(Array.Empty()), - [2] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.False(renderTask.IsCompleted); - tcs.SetResult(0); - - await renderTask; - Assert.Equal(2, renderer.HandledExceptions.Count); - Assert.Contains(exception1, renderer.HandledExceptions); - Assert.Contains(exception2, renderer.HandledExceptions); - } - - [Fact] - public void ExceptionsThrownSynchronouslyFromMultipleComponentsCanBeHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception1 = new InvalidTimeZoneException(); - var exception2 = new UriFormatException(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = Array.Empty(), - [1] = new List - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = () => - { - throw exception1; - } - }, - }, - [2] = new List - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnInitAsyncAsync, - EventAction = () => - { - throw exception2; - } - }, - }, - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1, 2, }), - [1] = CreateRenderFactory(Array.Empty()), - [2] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(renderTask.IsCompletedSuccessfully); - - Assert.Equal(2, renderer.HandledExceptions.Count); - Assert.Contains(exception1, renderer.HandledExceptions); - Assert.Contains(exception2, renderer.HandledExceptions); - } - - [Fact] - public async Task ExceptionsThrownFromHandleAfterRender_Sync_AreHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception = new InvalidTimeZoneException(); - - var taskCompletionSource = new TaskCompletionSource(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncSync, - EventAction = () => - { - throw exception; - }, - } - }, - [1] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncSync, - EventAction = () => - { - taskCompletionSource.TrySetResult(0); - return Task.FromResult((1, NestedAsyncComponent.EventType.OnAfterRenderAsyncSync)); - }, - } - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1 }), - [1] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(renderTask.IsCompletedSuccessfully); - - // OnAfterRenderAsync happens in the background. Make it more predictable, by gating it until we're ready to capture exceptions. - await taskCompletionSource.Task.TimeoutAfter(TimeSpan.FromSeconds(10)); - Assert.Same(exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - [Fact] - public async Task ExceptionsThrownFromHandleAfterRender_Async_AreHandled() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var exception = new InvalidTimeZoneException(); - - var taskCompletionSource = new TaskCompletionSource(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncAsync, - EventAction = async () => - { - await Task.Yield(); - throw exception; - }, - } - }, - [1] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncAsync, - EventAction = async () => - { - await Task.Yield(); - taskCompletionSource.TrySetResult(0); - return (1, NestedAsyncComponent.EventType.OnAfterRenderAsyncAsync); - }, - } - } - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(new[] { 1 }), - [1] = CreateRenderFactory(Array.Empty()), - }, - })); - - Assert.True(renderTask.IsCompletedSuccessfully); - - // OnAfterRenderAsync happens in the background. Make it more predictable, by gating it until we're ready to capture exceptions. - await taskCompletionSource.Task.TimeoutAfter(TimeSpan.FromSeconds(10)); - Assert.Same(exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - [Fact] - public async Task ExceptionThrownFromConstructor() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - await renderTask; - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Same(ConstructorThrowingComponent.Exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - private class ConstructorThrowingComponent : IComponent - { - public static readonly Exception Exception = new InvalidTimeZoneException(); - - public ConstructorThrowingComponent() - { - throw Exception; - } - - public void Attach(RenderHandle renderHandle) - { - throw new NotImplementedException(); - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - - [Fact] - public async Task ExceptionThrownFromAttach() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId); - - await renderTask; - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Same(AttachThrowingComponent.Exception, Assert.Single(renderer.HandledExceptions).GetBaseException()); - } - - private class AttachThrowingComponent : IComponent - { - public static readonly Exception Exception = new InvalidTimeZoneException(); - - public void Attach(RenderHandle renderHandle) - { - throw Exception; - } - - public Task SetParametersAsync(ParameterView parameters) - { - throw new NotImplementedException(); - } - } - - [Fact] - public void SynchronousCancelledTasks_HandleAfterRender_Works() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var tcs = new TaskCompletionSource<(int, NestedAsyncComponent.EventType)>(); - tcs.TrySetCanceled(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncAsync, - EventAction = () => tcs.Task, - } - }, - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - // Rendering should finish synchronously - Assert.True(renderTask.IsCompletedSuccessfully); - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public void AsynchronousCancelledTasks_HandleAfterRender_Works() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var tcs = new TaskCompletionSource<(int, NestedAsyncComponent.EventType)>(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncAsync, - EventAction = () => tcs.Task, - } - }, - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - // Rendering should be complete. - Assert.True(renderTask.IsCompletedSuccessfully); - tcs.TrySetCanceled(); - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public async Task CanceledTasksInHandleAfterRender_AreIgnored() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var component = new NestedAsyncComponent(); - var taskCompletionSource = new TaskCompletionSource(); - var cancellationTokenSource = new CancellationTokenSource(); - cancellationTokenSource.Cancel(); - - // Act/Assert - var componentId = renderer.AssignRootComponentId(component); - await renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary - { - [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> - { - [0] = new[] - { - new NestedAsyncComponent.ExecutionAction - { - Event = NestedAsyncComponent.EventType.OnAfterRenderAsyncSync, - EventAction = () => - { - taskCompletionSource.TrySetResult(0); - cancellationTokenSource.Token.ThrowIfCancellationRequested(); - return default; - }, - } - }, - }, - [nameof(NestedAsyncComponent.WhatToRender)] = new Dictionary> - { - [0] = CreateRenderFactory(Array.Empty()), - }, - })); - - await taskCompletionSource.Task.TimeoutAfter(TimeSpan.FromSeconds(10)); - - Assert.Empty(renderer.HandledExceptions); - } - - [Fact] - public void DisposingRenderer_DisposesTopLevelComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new DisposableComponent(); - renderer.AssignRootComponentId(component); - - // Act - renderer.Dispose(); - - // Assert - Assert.True(component.Disposed); - } - - [Fact] - public void DisposingRenderer_RejectsAttemptsToStartMoreRenderBatches() - { - // Arrange - var renderer = new TestRenderer(); - renderer.Dispose(); - - // Act/Assert - var ex = Assert.Throws(() => renderer.ProcessPendingRender()); - Assert.Contains("Cannot process pending renders after the renderer has been disposed.", ex.Message); - } - - [Fact] - public void WhenRendererIsDisposed_ComponentRenderRequestsAreSkipped() - { - // The important point of this is that user code in components may continue to call - // StateHasChanged (e.g., after an async task completion), and we don't want that to - // show up as an error. In general, components should skip rendering after disposal. - // This test shows that we don't add any new entries to the render queue after disposal. - // There's a different test showing that if the render queue entry was already added - // before a component got individually disposed, that render queue entry gets skipped. - - // Arrange - var renderer = new TestRenderer(); - var component = new DisposableComponent(); - renderer.AssignRootComponentId(component); - - // Act - renderer.Dispose(); - component.TriggerRender(); - - // Assert: no exception, no batch produced - Assert.Empty(renderer.Batches); - } - - [Fact] - public void DisposingRenderer_DisposesNestedComponents() - { - // Arrange - var renderer = new TestRenderer(); - var component = new TestComponent(builder => - { - builder.AddContent(0, "Hello"); - builder.OpenComponent(1); - builder.CloseComponent(); - }); - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - var batch = renderer.Batches.Single(); - var componentFrame = batch.ReferenceFrames - .Single(frame => frame.FrameType == RenderTreeFrameType.Component); - var nestedComponent = Assert.IsType(componentFrame.Component); - - // Act - renderer.Dispose(); - - // Assert - Assert.True(component.Disposed); - Assert.True(nestedComponent.Disposed); - } - - [Fact] - public void DisposingRenderer_CapturesExceptionsFromAllRegisteredComponents() - { - // Arrange - var renderer = new TestRenderer { ShouldHandleExceptions = true }; - var exception1 = new Exception(); - var exception2 = new Exception(); - var component = new TestComponent(builder => - { - builder.AddContent(0, "Hello"); - builder.OpenComponent(1); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => throw exception1)); - builder.CloseComponent(); - - builder.OpenComponent(2); - builder.AddAttribute(1, nameof(DisposableComponent.DisposeAction), (Action)(() => throw exception2)); - builder.CloseComponent(); - }); - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - // Act &A Assert - renderer.Dispose(); - - // All components must be disposed even if some throw as part of being diposed. - Assert.True(component.Disposed); - var aex = Assert.IsType(Assert.Single(renderer.HandledExceptions)); - Assert.Contains(exception1, aex.InnerExceptions); - Assert.Contains(exception2, aex.InnerExceptions); - } - - [Theory] - [InlineData(null)] // No existing attribute to update - [InlineData("old property value")] // Has existing attribute to update - public void EventFieldInfoCanPatchTreeSoDiffDoesNotUpdateAttribute(string oldValue) - { - // Arrange: Render a component with an event handler - var renderer = new TestRenderer(); - var component = new BoundPropertyComponent { BoundString = oldValue }; - var componentId = renderer.AssignRootComponentId(component); - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.FrameType == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerId > 0) - .AttributeEventHandlerId; - - // Act: Fire event and re-render - var eventFieldInfo = new EventFieldInfo - { - FieldValue = "new property value", - ComponentId = componentId - }; - var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, eventFieldInfo, new ChangeEventArgs - { - Value = "new property value" - }); - Assert.True(dispatchEventTask.IsCompletedSuccessfully); - - // Assert: Property was updated, but the diff doesn't include changing the - // element attribute, since we told it the element attribute was already updated - Assert.Equal("new property value", component.BoundString); - Assert.Equal(2, renderer.Batches.Count); - var batch2 = renderer.Batches[1]; - Assert.Collection(batch2.DiffsInOrder.Single().Edits.ToArray(), edit => - { - // The only edit is updating the event handler ID, since the test component - // deliberately uses a capturing lambda. The whole point of this test is to - // show that the diff does *not* update the BoundString value attribute. - Assert.Equal(RenderTreeEditType.SetAttribute, edit.Type); - var attributeFrame = batch2.ReferenceFrames[edit.ReferenceFrameIndex]; - AssertFrame.Attribute(attributeFrame, "ontestevent", typeof(Action)); - Assert.NotEqual(default, attributeFrame.AttributeEventHandlerId); - Assert.NotEqual(eventHandlerId, attributeFrame.AttributeEventHandlerId); - }); - } - - [Fact] - public void EventFieldInfoWorksWhenEventHandlerIdWasSuperseded() - { - // Arrange: Render a component with an event handler - // We want the renderer to think none of the "UpdateDisplay" calls ever complete, because we - // want to keep reusing the same eventHandlerId and not let it get disposed - var renderCompletedTcs = new TaskCompletionSource(); - var renderer = new TestRenderer { NextRenderResultTask = renderCompletedTcs.Task }; - var component = new BoundPropertyComponent { BoundString = "old property value" }; - var componentId = renderer.AssignRootComponentId(component); - - component.TriggerRender(); - - var eventHandlerId = renderer.Batches.Single() - .ReferenceFrames - .First(frame => frame.FrameType == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerId > 0) - .AttributeEventHandlerId; - - // Act: Fire event and re-render *repeatedly*, without changing to use a newer event handler ID, - // even though we know the event handler ID is getting updated in successive diffs - for (var i = 0; i < 10; i++) - { - var newPropertyValue = $"new property value {i}"; - var fieldInfo = new EventFieldInfo - { - ComponentId = componentId, - FieldValue = newPropertyValue, - }; - var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, fieldInfo, new ChangeEventArgs - { - Value = newPropertyValue - }); - Assert.True(dispatchEventTask.IsCompletedSuccessfully); - - // Assert: Property was updated, but the diff doesn't include changing the - // element attribute, since we told it the element attribute was already updated - Assert.Equal(newPropertyValue, component.BoundString); - Assert.Equal(i + 2, renderer.Batches.Count); - var latestBatch = renderer.Batches.Last(); - Assert.Collection(latestBatch.DiffsInOrder.Single().Edits.ToArray(), edit => - { - // The only edit is updating the event handler ID, since the test component - // deliberately uses a capturing lambda. The whole point of this test is to - // show that the diff does *not* update the BoundString value attribute. - Assert.Equal(RenderTreeEditType.SetAttribute, edit.Type); - var attributeFrame = latestBatch.ReferenceFrames[edit.ReferenceFrameIndex]; - AssertFrame.Attribute(attributeFrame, "ontestevent", typeof(Action)); - Assert.NotEqual(default, attributeFrame.AttributeEventHandlerId); - Assert.NotEqual(eventHandlerId, attributeFrame.AttributeEventHandlerId); - }); - } - } - - [Fact] - public void CannotStartOverlappingBatches() - { - // Arrange - var renderer = new InvalidRecursiveRenderer(); - var component = new CallbackOnRenderComponent(() => - { - // The renderer disallows one batch to be started inside another, because that - // would violate all kinds of state tracking invariants. It's not something that - // would ever happen except if you subclass the renderer and do something unsupported - // that commences batches from inside each other. - renderer.ProcessPendingRender(); - }); - var componentId = renderer.AssignRootComponentId(component); - - // Act/Assert - var ex = Assert.Throws( - () => renderer.RenderRootComponent(componentId)); - Assert.Contains("Cannot start a batch when one is already in progress.", ex.Message); - } - - [Fact] - public void CannotAccessParameterViewAfterSynchronousReturn() - { - // Arrange - var renderer = new TestRenderer(); - var rootComponent = new TestComponent(builder => - { - builder.OpenComponent(0); - builder.AddAttribute(1, nameof(ParameterViewIllegalCapturingComponent.SomeParam), 0); - builder.CloseComponent(); - }); - var rootComponentId = renderer.AssignRootComponentId(rootComponent); - - // Note that we're not waiting for the async render to complete, since we want to assert - // about the situation immediately after the component yields the thread - renderer.RenderRootComponentAsync(rootComponentId); - - // Act/Assert - var capturingComponent = (ParameterViewIllegalCapturingComponent)renderer.GetCurrentRenderTreeFrames(rootComponentId).Array[0].Component; - var parameterView = capturingComponent.CapturedParameterView; - - // All public APIs on capturingComponent should be electrified now - // Internal APIs don't have to be, because we won't call them at the wrong time - Assert.Throws(() => parameterView.GetEnumerator()); - Assert.Throws(() => parameterView.GetValueOrDefault("anything")); - Assert.Throws(() => parameterView.SetParameterProperties(new object())); - Assert.Throws(() => parameterView.ToDictionary()); - var ex = Assert.Throws(() => parameterView.TryGetValue("anything", out _)); - - // It's enough to assert about one of the messages - Assert.Equal($"The {nameof(ParameterView)} instance can no longer be read because it has expired. {nameof(ParameterView)} can only be read synchronously and must not be stored for later use.", ex.Message); - } - - private class NoOpRenderer : Renderer - { - public NoOpRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance) - { - } - - public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); - - public new int AssignRootComponentId(IComponent component) - => base.AssignRootComponentId(component); - - protected override void HandleException(Exception exception) - => throw new NotImplementedException(); - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - => Task.CompletedTask; - } - - private class TestComponent : IComponent, IDisposable - { - private RenderHandle _renderHandle; - private RenderFragment _renderFragment; - - public TestComponent(RenderFragment renderFragment) - { - _renderFragment = renderFragment; - } - - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - public Task SetParametersAsync(ParameterView parameters) - { - TriggerRender(); - return Task.CompletedTask; - } - - public void TriggerRender() - { - var t = _renderHandle.Dispatcher.InvokeAsync(() => _renderHandle.Render(_renderFragment)); - // This should always be run synchronously - Assert.True(t.IsCompleted); - if (t.IsFaulted) - { - var exception = t.Exception.Flatten().InnerException; - while (exception is AggregateException e) - { - exception = e.InnerException; - } - ExceptionDispatchInfo.Capture(exception).Throw(); - } - } - - public bool Disposed { get; private set; } - - void IDisposable.Dispose() => Disposed = true; - } - - private class MessageComponent : AutoRenderComponent - { - [Parameter] - public string Message { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, Message); - } - } - - private class MyStrongComponent : AutoRenderComponent - { - [Parameter(CaptureUnmatchedValues = true)] public IDictionary Attributes { get; set; } - - [Parameter] public string Text { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenElement(0, "strong"); - builder.AddMultipleAttributes(1, Attributes); - builder.AddContent(2, Text); - builder.CloseElement(); - } - } - - private class FakeComponent : IComponent - { - [Parameter] - public int IntProperty { get; set; } - - [Parameter] - public string StringProperty { get; set; } - - [Parameter] - public object ObjectProperty { get; set; } - - public RenderHandle RenderHandle { get; private set; } - - public void Attach(RenderHandle renderHandle) - => RenderHandle = renderHandle; - - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - return Task.CompletedTask; - } - } - - private class EventComponent : AutoRenderComponent, IComponent, IHandleEvent - { - [Parameter] - public Action OnTest { get; set; } - - [Parameter] - public Func OnTestAsync { get; set; } - - [Parameter] - public Action OnClick { get; set; } - - [Parameter] - public Func OnClickAsync { get; set; } - - [Parameter] - public Action OnClickAction { get; set; } - - [Parameter] - public Func OnClickAsyncAction { get; set; } - - [Parameter] - public EventCallback OnClickEventCallback { get; set; } - - [Parameter] - public EventCallback OnClickEventCallbackOfT { get; set; } - - public bool SkipElement { get; set; } - private int renderCount = 0; - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenElement(0, "grandparent"); - if (!SkipElement) - { - builder.OpenElement(1, "parent"); - builder.OpenElement(2, "some element"); - - if (OnTest != null) - { - builder.AddAttribute(3, "ontest", OnTest); - } - else if (OnTestAsync != null) - { - builder.AddAttribute(3, "ontest", OnTestAsync); - } - - if (OnClick != null) - { - builder.AddAttribute(4, "onclick", OnClick); - } - else if (OnClickAsync != null) - { - builder.AddAttribute(4, "onclick", OnClickAsync); - } - else if (OnClickEventCallback.HasDelegate) - { - builder.AddAttribute(4, "onclick", OnClickEventCallback); - } - else if (OnClickEventCallbackOfT.HasDelegate) - { - builder.AddAttribute(4, "onclick", OnClickEventCallbackOfT); - } - - if (OnClickAction != null) - { - builder.AddAttribute(5, "onclickaction", OnClickAction); - } - else if (OnClickAsyncAction != null) - { - builder.AddAttribute(5, "onclickaction", OnClickAsyncAction); - } - builder.CloseElement(); - builder.CloseElement(); - } - builder.CloseElement(); - builder.AddContent(6, $"Render count: {++renderCount}"); - } - - public Task HandleEventAsync(EventCallbackWorkItem callback, object arg) - { - // Notice, we don't re-render. - return callback.InvokeAsync(arg); - } - } - - private class ConditionalParentComponent : AutoRenderComponent where T : IComponent - { - [Parameter] - public bool IncludeChild { get; set; } - - [Parameter] - public IDictionary ChildParameters { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "Parent here"); - - if (IncludeChild) - { - builder.OpenComponent(1); - if (ChildParameters != null) - { - var sequence = 2; - foreach (var kvp in ChildParameters) - { - builder.AddAttribute(sequence++, kvp.Key, kvp.Value); - } - } - builder.CloseComponent(); - } - } - } - - private class ReRendersParentComponent : AutoRenderComponent - { - [Parameter] - public TestComponent Parent { get; set; } - - private bool _isFirstTime = true; - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - if (_isFirstTime) // Don't want an infinite loop - { - _isFirstTime = false; - Parent.TriggerRender(); - } - - builder.AddContent(0, "Child is here"); - } - } - - private class RendersSelfAfterEventComponent : IComponent, IHandleEvent - { - [Parameter] - public Action OnClick { get; set; } - - private RenderHandle _renderHandle; - - public void Attach(RenderHandle renderHandle) - => _renderHandle = renderHandle; - - public Task SetParametersAsync(ParameterView parameters) - { - parameters.SetParameterProperties(this); - Render(); - return Task.CompletedTask; - } - - public Task HandleEventAsync(EventCallbackWorkItem callback, object arg) - { - var task = callback.InvokeAsync(arg); - Render(); - return task; - } - - private void Render() - => _renderHandle.Render(builder => - { - builder.OpenElement(0, "my button"); - builder.AddAttribute(1, "onmycustomevent", EventCallback.Factory.Create(this, eventArgs => OnClick(eventArgs))); - builder.CloseElement(); - }); - } - - private class MultiRendererComponent : IComponent - { - private readonly List _renderHandles - = new List(); - - public void Attach(RenderHandle renderHandle) - => _renderHandles.Add(renderHandle); - - public Task SetParametersAsync(ParameterView parameters) - { - return Task.CompletedTask; - } - - public void TriggerRender() - { - foreach (var renderHandle in _renderHandles) - { - renderHandle.Dispatcher.InvokeAsync(() => renderHandle.Render(builder => - { - builder.AddContent(0, $"Hello from {nameof(MultiRendererComponent)}"); - })); - } - } - } - - private class BindPlusConditionalAttributeComponent : AutoRenderComponent, IHandleEvent - { - public bool CheckboxEnabled; - public string SomeStringProperty; - - public Task HandleEventAsync(EventCallbackWorkItem callback, object arg) - { - var task = callback.InvokeAsync(arg); - TriggerRender(); - return task; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenElement(0, "input"); - builder.AddAttribute(1, "type", "checkbox"); - builder.AddAttribute(2, "value", BindConverter.FormatValue(CheckboxEnabled)); - builder.AddAttribute(3, "onchange", EventCallback.Factory.CreateBinder(this, __value => CheckboxEnabled = __value, CheckboxEnabled)); - builder.CloseElement(); - builder.OpenElement(4, "input"); - builder.AddAttribute(5, "value", BindConverter.FormatValue(SomeStringProperty)); - builder.AddAttribute(6, "onchange", EventCallback.Factory.CreateBinder(this, __value => SomeStringProperty = __value, SomeStringProperty)); - builder.AddAttribute(7, "disabled", !CheckboxEnabled); - builder.CloseElement(); - } - } - - private class AfterRenderCaptureComponent : AutoRenderComponent, IComponent, IHandleAfterRender - { - public Action OnAfterRenderLogic { get; set; } - - public int OnAfterRenderCallCount { get; private set; } - - public Task OnAfterRenderAsync() - { - OnAfterRenderCallCount++; - OnAfterRenderLogic?.Invoke(); - return Task.CompletedTask; - } - - Task IComponent.SetParametersAsync(ParameterView parameters) - { - TriggerRender(); - return Task.CompletedTask; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - } - } - - private class DisposableComponent : AutoRenderComponent, IDisposable - { - public bool Disposed { get; private set; } - - [Parameter] - public Action DisposeAction { get; set; } - - public void Dispose() - { - Disposed = true; - DisposeAction?.Invoke(); - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - } - } - - class TestAsyncRenderer : TestRenderer - { - public Task NextUpdateDisplayReturnTask { get; set; } - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - { - base.UpdateDisplayAsync(renderBatch); - return NextUpdateDisplayReturnTask; - } - } - - private class AsyncComponent : IComponent - { - private RenderHandle _renderHandler; - - public AsyncComponent(Task taskToAwait, int number) - { - _taskToAwait = taskToAwait; - Number = number; - } - - private readonly Task _taskToAwait; - - public int Number { get; set; } - - public void Attach(RenderHandle renderHandle) - { - _renderHandler = renderHandle; - } - - public async Task SetParametersAsync(ParameterView parameters) - { - int n; - while (Number > 0) - { - n = Number; - _renderHandler.Render(CreateFragment); - Number--; - await _taskToAwait; - }; - - // Cheap closure - void CreateFragment(RenderTreeBuilder builder) - { - var s = 0; - builder.OpenElement(s++, "p"); - builder.AddContent(s++, n); - builder.CloseElement(); - } - } - } - - private class OuterEventComponent : IComponent, IHandleEvent - { - private RenderHandle _renderHandle; - - public RenderFragment RenderFragment { get; set; } - - public Action OnEvent { get; set; } - - public int SomeMethodCallCount { get; set; } - - public void SomeMethod() - { - SomeMethodCallCount++; - } - - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - public Task HandleEventAsync(EventCallbackWorkItem callback, object arg) - { - var task = callback.InvokeAsync(arg); - OnEvent?.Invoke(); - return task; - } - - public Task SetParametersAsync(ParameterView parameters) - { - return TriggerRenderAsync(); - } - - public Task TriggerRenderAsync() => _renderHandle.Dispatcher.InvokeAsync(() => _renderHandle.Render(RenderFragment)); - } - - private void AssertStream(int expectedId, (int id, NestedAsyncComponent.EventType @event)[] logStream) - { - // OnInit runs first - Assert.Equal((expectedId, NestedAsyncComponent.EventType.OnInit), logStream[0]); - - // OnInit async completes - Assert.Single(logStream.Skip(1), - e => e == (expectedId, NestedAsyncComponent.EventType.OnInitAsyncAsync) || e == (expectedId, NestedAsyncComponent.EventType.OnInitAsyncSync)); - - var parametersSetEvent = logStream.Where(le => le == (expectedId, NestedAsyncComponent.EventType.OnParametersSet)).ToArray(); - // OnParametersSet gets called at least once - Assert.NotEmpty(parametersSetEvent); - - var parametersSetAsyncEvent = logStream - .Where(le => le == (expectedId, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync) || - le == (expectedId, NestedAsyncComponent.EventType.OnParametersSetAsyncSync)) - .ToArray(); - // OnParametersSetAsync async gets called at least once - Assert.NotEmpty(parametersSetAsyncEvent); - - // The same number of OnParametersSet and OnParametersSetAsync get produced - Assert.Equal(parametersSetEvent.Length, parametersSetAsyncEvent.Length); - - // The log ends with an OnParametersSetAsync event - Assert.True(logStream.Last() == (expectedId, NestedAsyncComponent.EventType.OnParametersSetAsyncSync) || - logStream.Last() == (expectedId, NestedAsyncComponent.EventType.OnParametersSetAsyncAsync)); - } - - private Func CreateRenderFactory(int[] childrenToRender) - { - // For some reason nameof doesn't work inside a nested lambda, so capturing the value here. - var eventActionsName = nameof(NestedAsyncComponent.EventActions); - var whatToRenderName = nameof(NestedAsyncComponent.WhatToRender); - var testIdName = nameof(NestedAsyncComponent.TestId); - var logName = nameof(NestedAsyncComponent.Log); - - return component => builder => - { - var s = 0; - builder.OpenElement(s++, "div"); - builder.AddContent(s++, $"Id: {component.TestId} BuildRenderTree, {Guid.NewGuid()}"); - foreach (var child in childrenToRender) - { - builder.OpenComponent(s++); - builder.AddAttribute(s++, eventActionsName, component.EventActions); - builder.AddAttribute(s++, whatToRenderName, component.WhatToRender); - builder.AddAttribute(s++, testIdName, child); - builder.AddAttribute(s++, logName, component.Log); - builder.CloseComponent(); - } - - builder.CloseElement(); - }; - } - - private class NestedAsyncComponent : ComponentBase - { - [Parameter] public IDictionary> EventActions { get; set; } - - [Parameter] public IDictionary> WhatToRender { get; set; } - - [Parameter] public int TestId { get; set; } - - [Parameter] public ConcurrentQueue<(int testId, EventType @event)> Log { get; set; } - - protected override void OnInitialized() - { - if (TryGetEntry(EventType.OnInit, out var entry)) - { - var result = entry.EventAction(); - Assert.True(result.IsCompleted, "Task must complete synchronously."); - LogResult(result.Result); - } - } - - protected override async Task OnInitializedAsync() - { - if (TryGetEntry(EventType.OnInitAsyncSync, out var entrySync)) - { - var result = entrySync.EventAction(); - Assert.True(result.IsCompleted, "Task must complete synchronously."); - LogResult(result.Result); - } - else if (TryGetEntry(EventType.OnInitAsyncAsync, out var entryAsync)) - { - var result = await entryAsync.EventAction(); - LogResult(result); - } - } - - protected override void OnParametersSet() - { - if (TryGetEntry(EventType.OnParametersSet, out var entry)) - { - var result = entry.EventAction(); - Assert.True(result.IsCompleted, "Task must complete synchronously."); - LogResult(result.Result); - } - base.OnParametersSet(); - } - - protected override async Task OnParametersSetAsync() - { - if (TryGetEntry(EventType.OnParametersSetAsyncSync, out var entrySync)) - { - var result = entrySync.EventAction(); - Assert.True(result.IsCompleted, "Task must complete synchronously."); - LogResult(result.Result); - } - else if (TryGetEntry(EventType.OnParametersSetAsyncAsync, out var entryAsync)) - { - var result = await entryAsync.EventAction(); - LogResult(result); - } - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - var renderFactory = WhatToRender[TestId]; - renderFactory(this)(builder); - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (TryGetEntry(EventType.OnAfterRenderAsyncSync, out var entrySync)) - { - var result = entrySync.EventAction(); - Assert.True(result.IsCompleted, "Task must complete synchronously."); - LogResult(result.Result); - } - if (TryGetEntry(EventType.OnAfterRenderAsyncAsync, out var entryAsync)) - { - var result = await entryAsync.EventAction(); - LogResult(result); - } - } - - private bool TryGetEntry(EventType eventType, out ExecutionAction entry) - { - var entries = EventActions[TestId]; - if (entries == null) - { - throw new InvalidOperationException("Failed to find entries for component with Id: " + TestId); - } - entry = entries.FirstOrDefault(e => e.Event == eventType); - return entry != null; - } - - private void LogResult((int, EventType) entry) - { - Log?.Enqueue(entry); - } - - public class ExecutionAction - { - public EventType Event { get; set; } - public Func> EventAction { get; set; } - - public static ExecutionAction On(int id, EventType @event, bool async = false) - { - if (!async) - { - return new ExecutionAction - { - Event = @event, - EventAction = () => Task.FromResult((id, @event)) - }; - } - else - { - return new ExecutionAction - { - Event = @event, - EventAction = async () => - { - await Task.Yield(); - return (id, @event); - } - }; - } - } - } - - public enum EventType - { - OnInit, - OnInitAsyncSync, - OnInitAsyncAsync, - OnParametersSet, - OnParametersSetAsyncSync, - OnParametersSetAsyncAsync, - OnAfterRenderAsyncSync, - OnAfterRenderAsyncAsync, - } - } - - private class ComponentThatAwaitsTask : ComponentBase - { - [Parameter] public Task TaskToAwait { get; set; } - - protected override async Task OnParametersSetAsync() - { - await TaskToAwait; - } - } - - private class AsyncUpdateTestRenderer : TestRenderer - { - public Func OnUpdateDisplayAsync { get; set; } - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - { - return OnUpdateDisplayAsync(renderBatch); - } - } - - private class AsyncAfterRenderComponent : AutoRenderComponent, IHandleAfterRender - { - private readonly Task _task; - - public AsyncAfterRenderComponent(Task task) - { - _task = task; - } - - public bool Called { get; private set; } - - public Action OnAfterRenderComplete { get; set; } - - public async Task OnAfterRenderAsync() - { - await _task; - Called = true; - - OnAfterRenderComplete?.Invoke(); - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.OpenElement(0, "p"); - builder.CloseElement(); - } - } - - class BoundPropertyComponent : AutoRenderComponent - { - public string BoundString { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - var unrelatedThingToMakeTheLambdaCapture = new object(); - - builder.OpenElement(0, "element with event"); - builder.AddAttribute(1, nameof(BoundString), BoundString); - builder.AddAttribute(2, "ontestevent", new Action((ChangeEventArgs eventArgs) => - { - BoundString = (string)eventArgs.Value; - TriggerRender(); - GC.KeepAlive(unrelatedThingToMakeTheLambdaCapture); - })); - builder.SetUpdatesAttributeName(nameof(BoundString)); - builder.CloseElement(); - } - } - - private class DerivedEventArgs : EventArgs - { - } - - class CallbackOnRenderComponent : AutoRenderComponent - { - private readonly Action _callback; - - public CallbackOnRenderComponent(Action callback) - { - _callback = callback; - } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - => _callback(); - } - - class InvalidRecursiveRenderer : TestRenderer - { - public new void ProcessPendingRender() - => base.ProcessPendingRender(); - } - - class ParameterViewIllegalCapturingComponent : IComponent - { - public ParameterView CapturedParameterView { get; private set; } - - [Parameter] public int SomeParam { get; set; } - - public void Attach(RenderHandle renderHandle) - { - } - - public Task SetParametersAsync(ParameterView parameters) - { - CapturedParameterView = parameters; - - // Return a task that never completes to show that access is forbidden - // after the synchronous return, not just after the returned task completes - return new TaskCompletionSource().Task; - } - } - } -} diff --git a/src/Components/Components/test/Rendering/ArrayBuilderSegmentTest.cs b/src/Components/Components/test/Rendering/ArrayBuilderSegmentTest.cs deleted file mode 100644 index 3e6a22fb6fed..000000000000 --- a/src/Components/Components/test/Rendering/ArrayBuilderSegmentTest.cs +++ /dev/null @@ -1,55 +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 Microsoft.AspNetCore.Components.RenderTree; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - public class ArrayBuilderSegmentTest - { - [Fact] - public void BasicPropertiesWork() - { - // Arrange: builder containing 1..5 - using var builder = new ArrayBuilder(); - builder.Append(new[] { 1, 2, 3, 4, 5 }, 0, 5); - - // Act: take segment containing 2..3 - var segment = builder.ToSegment(1, 3); - - // Act - Assert.Same(builder.Buffer, segment.Array); - Assert.Equal(1, segment.Offset); - Assert.Equal(2, segment.Count); - Assert.Equal(2, segment[0]); - Assert.Equal(3, segment[1]); - Assert.Equal(new[] { 2, 3 }, segment); - } - - [Fact] - public void StillWorksAfterUnderlyingCapacityChange() - { - // Arrange: builder containing 1..8 - using var builder = new ArrayBuilder(minCapacity: 10, new TestArrayPool()); - builder.Append(new[] { 1, 2, 3, 4, 5, 6, 7, 8 }, 0, 8); - var originalBuffer = builder.Buffer; - - // Act/Assert 1: take segment containing 1..5 - var segment = builder.ToSegment(0, 5); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, segment); - Assert.Same(originalBuffer, segment.Array); - - // Act 2: grow the builder enough to force a resize - builder.Append(new[] { 9, 10, 11 }, 0, 3); - Array.Clear(originalBuffer, 0, originalBuffer.Length); // Extra proof that we're not using the original storage - - // Assert 2 - Assert.Same(builder.Buffer, segment.Array); - Assert.NotSame(originalBuffer, segment.Array); // Since there was a resize - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, segment); - Assert.Equal(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, builder.ToSegment(0, builder.Count)); - } - } -} diff --git a/src/Components/Components/test/Rendering/ArrayBuilderTest.cs b/src/Components/Components/test/Rendering/ArrayBuilderTest.cs deleted file mode 100644 index d1aae06064d4..000000000000 --- a/src/Components/Components/test/Rendering/ArrayBuilderTest.cs +++ /dev/null @@ -1,334 +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.Buffers; -using System.Linq; -using Xunit; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - public class ArrayBuilderTest - { - private readonly TestArrayPool ArrayPool = new TestArrayPool(); - - [Fact] - public void Append_SingleItem() - { - // Arrange - var value = 7; - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(value); - - // Assert - Assert.Equal(1, builder.Count); - Assert.Equal(value, builder.Buffer[0]); - } - - [Fact] - public void Append_ThreeItem() - { - // Arrange - var value1 = 7; - var value2 = 22; - var value3 = 3; - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(value1); - builder.Append(value2); - builder.Append(value3); - - // Assert - Assert.Equal(3, builder.Count); - Assert.Equal(new[] { value1, value2, value3 }, builder.Buffer.Take(3)); - } - - [Fact] - public void Append_FillBuffer() - { - // Arrange - var capacity = 8; - using var builder = new ArrayBuilder(minCapacity: capacity); - - // Act - for (var i = 0; i < capacity; i++) - { - builder.Append(5); - } - - // Assert - Assert.Equal(capacity, builder.Count); - Assert.Equal(Enumerable.Repeat(5, capacity), builder.Buffer.Take(capacity)); - } - - [Fact] - public void AppendArray_CopySubset() - { - // Arrange - var array = Enumerable.Repeat(8, 5).ToArray(); - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(array, 0, 2); - - // Assert - Assert.Equal(2, builder.Count); - Assert.Equal(new[] { 8, 8 }, builder.Buffer.Take(2)); - } - - [Fact] - public void AppendArray_CopyArray() - { - // Arrange - var array = Enumerable.Repeat(8, 5).ToArray(); - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(array, 0, array.Length); - - // Assert - Assert.Equal(array.Length, builder.Count); - Assert.Equal(array, builder.Buffer.Take(array.Length)); - } - - [Fact] - public void AppendArray_AfterPriorInsertion() - { - // Arrange - var array = Enumerable.Repeat(8, 5).ToArray(); - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(118); - builder.Append(array, 0, 2); - - // Assert - Assert.Equal(3, builder.Count); - Assert.Equal(new[] { 118, 8, 8 }, builder.Buffer.Take(3)); - } - - [Theory] - // These are at boundaries of our capacity increments. - [InlineData(1023)] - [InlineData(1024)] - [InlineData(1025)] - public void AppendArray_LargerThanBuffer(int size) - { - // Arrange - var array = Enumerable.Repeat(17, size).ToArray(); - using var builder = CreateArrayBuilder(); - - // Act - builder.Append(array, 0, array.Length); - - // Assert - Assert.Equal(array.Length, builder.Count); - Assert.Equal(array, builder.Buffer.Take(array.Length)); - } - - [Fact] - public void Overwrite_Works() - { - // Arrange - using var builder = CreateArrayBuilder(); - builder.Append(7); - builder.Append(3); - builder.Append(9); - - // Act - builder.Overwrite(1, 2); - - // Assert - Assert.Equal(3, builder.Count); - Assert.Equal(new[]{ 7, 2, 9}, builder.Buffer.Take(3)); - } - - [Fact] - public void Insert_Works() - { - // Arrange - using var builder = CreateArrayBuilder(); - builder.Append(7); - builder.Append(3); - builder.Append(9); - - // Act - builder.InsertExpensive(1, 2); - - // Assert - Assert.Equal(4, builder.Count); - Assert.Equal(new[] { 7, 2, 3, 9 }, builder.Buffer.Take(4)); - } - - [Fact] - public void Insert_WhenBufferIsAtCapacity() - { - // Arrange - using var builder = CreateArrayBuilder(2); - builder.Append(new[] { 1, 3 }, 0, 2); - - // Act - builder.InsertExpensive(1, 2); - - // Assert - Assert.Equal(3, builder.Count); - Assert.Equal(new[] { 1, 2, 3 }, builder.Buffer.Take(3)); - } - - [Fact] - public void RemoveLast_Works() - { - // Arrange - using var builder = CreateArrayBuilder(); - builder.Append(1); - builder.Append(2); - builder.Append(3); - - // Act - builder.RemoveLast(); - - // Assert - Assert.Equal(2, builder.Count); - Assert.Equal(new[] { 1, 2, }, builder.Buffer.Take(2)); - } - - [Fact] - public void RemoveLast_LastEntry() - { - // Arrange - int[] buffer; - using (var builder = CreateArrayBuilder()) - { - builder.Append(1); - buffer = builder.Buffer; - - // Act - builder.RemoveLast(); - - // Assert - Assert.Equal(0, builder.Count); - } - - // Also verify that the buffer is indeed returned in this case. - var returnedBuffer = Assert.Single(ArrayPool.ReturnedBuffers); - Assert.Same(buffer, returnedBuffer); - } - - [Fact] - public void Clear_ReturnsBuffer() - { - // Arrange - using var builder = CreateArrayBuilder(); - builder.Append(1); - var buffer = builder.Buffer; - - // Act - builder.Clear(); - - // Assert - Assert.Equal(0, builder.Count); - var returnedBuffer = Assert.Single(ArrayPool.ReturnedBuffers); - Assert.Same(buffer, returnedBuffer); - } - - [Fact] - public void Dispose_WithEmptyBuffer_DoesNotReturnIt() - { - // Arrange - var builder = CreateArrayBuilder(); - - // Act - builder.Dispose(); - - // Assert - Assert.Empty(ArrayPool.ReturnedBuffers); - } - - [Fact] - public void Dispose_NonEmptyBufferIsReturned() - { - // Arrange - var builder = CreateArrayBuilder(); - builder.Append(1); - var buffer = builder.Buffer; - - // Act - builder.Dispose(); - - // Assert - Assert.Single(ArrayPool.ReturnedBuffers); - var returnedBuffer = Assert.Single(ArrayPool.ReturnedBuffers); - Assert.Same(buffer, returnedBuffer); - Assert.NotSame(builder.Buffer, buffer); // Prevents use after free - } - - [Fact] - public void DoubleDispose_DoesNotReturnBufferTwice() - { - // Arrange - var builder = CreateArrayBuilder(); - builder.Append(1); - var buffer = builder.Buffer; - - // Act - builder.Dispose(); - builder.Dispose(); - - // Assert - Assert.Single(ArrayPool.ReturnedBuffers); - var returnedBuffer = Assert.Single(ArrayPool.ReturnedBuffers); - Assert.Same(buffer, returnedBuffer); - } - - [Fact] - public void Dispose_ThrowsOnReuse() - { - // Arrange - var builder = CreateArrayBuilder(); - builder.Append(1); - var buffer = builder.Buffer; - - builder.Dispose(); - Assert.Single(ArrayPool.ReturnedBuffers); - - // Act & Assert - Assert.Throws(() => builder.Append(1)); - } - - [Fact] - public void UnusedBufferIsReturned_OnResize() - { - // Arrange - var builder = CreateArrayBuilder(2); - - // Act - for (var i = 0; i < 10; i++) - { - builder.Append(i); - } - - // Assert - Assert.Collection( - ArrayPool.ReturnedBuffers, - buffer => Assert.Equal(2, buffer.Length), - buffer => Assert.Equal(4, buffer.Length), - buffer => Assert.Equal(8, buffer.Length)); - - // Clear this because this is no longer interesting. - ArrayPool.ReturnedBuffers.Clear(); - - var buffer = builder.Buffer; - builder.Dispose(); - - Assert.Same(buffer, Assert.Single(ArrayPool.ReturnedBuffers)); - } - - private ArrayBuilder CreateArrayBuilder(int capacity = 32) - { - return new ArrayBuilder(capacity, ArrayPool); - } - } -} diff --git a/src/Components/Components/test/Rendering/RenderTreeBuilderTest.cs b/src/Components/Components/test/Rendering/RenderTreeBuilderTest.cs deleted file mode 100644 index 31364dca008f..000000000000 --- a/src/Components/Components/test/Rendering/RenderTreeBuilderTest.cs +++ /dev/null @@ -1,1857 +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.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - public class RenderTreeBuilderTest - { - [Fact] - public void StartsEmpty() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Assert - var frames = builder.GetFrames(); - Assert.NotNull(frames.Array); - Assert.Empty(frames.AsEnumerable()); - } - - [Fact] - public void CanAddText() - { - // Arrange - var builder = new RenderTreeBuilder(); - var nullString = (string)null; - - // Act - builder.AddContent(0, "First item"); - builder.AddContent(0, nullString); - builder.AddContent(0, "Second item"); - - // Assert - var frames = builder.GetFrames(); - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Text(frame, "First item"), - frame => AssertFrame.Text(frame, string.Empty), - frame => AssertFrame.Text(frame, "Second item")); - } - - [Fact] - public void CanAddMarkup() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "some elem"); - builder.AddMarkupContent(1, "Blah"); - builder.AddMarkupContent(2, string.Empty); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames(); - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Element(frame, "some elem", 3), - frame => AssertFrame.Markup(frame, "Blah"), - frame => AssertFrame.Markup(frame, string.Empty)); - } - - [Fact] - public void CanAddMarkupViaMarkupString() - { - // This represents putting @someMarkupString into the component, - // as opposed to calling builder.AddMarkupContent directly. - - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - can use either constructor or cast - builder.AddContent(0, (MarkupString)"Some markup"); - builder.AddContent(1, new MarkupString(null)); - - // Assert - var frames = builder.GetFrames(); - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Markup(frame, "Some markup"), - frame => AssertFrame.Markup(frame, string.Empty)); - } - - [Fact] - public void CanAddNullMarkup() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.AddMarkupContent(0, null); - - // Assert - var frames = builder.GetFrames(); - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Markup(frame, string.Empty)); - } - - [Fact] - public void CanAddNonStringValueAsText() - { - // Arrange - var builder = new RenderTreeBuilder(); - var nullObject = (object)null; - - // Act - builder.AddContent(0, 1234); - builder.AddContent(0, nullObject); - - // Assert - var frames = builder.GetFrames(); - Assert.Collection(frames.AsEnumerable(), - frame => AssertFrame.Text(frame, "1234"), - frame => AssertFrame.Text(frame, string.Empty)); - } - - [Fact] - public void UnclosedElementsHaveNoSubtreeLength() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "my element"); - - // Assert - var frame = builder.GetFrames().AsEnumerable().Single(); - AssertFrame.Element(frame, "my element", 0); - } - - [Fact] - public void ClosedEmptyElementsHaveSubtreeLengthOne() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.AddContent(0, "some frame so that the element isn't at position zero"); - builder.OpenElement(0, "my element"); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames(); - Assert.Equal(2, frames.Count); - AssertFrame.Element(frames.Array[1], "my element", 1); - } - - [Fact] - public void ClosedElementsHaveCorrectSubtreeLength() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "my element"); - builder.AddContent(0, "child 1"); - builder.AddContent(0, "child 2"); - builder.CloseElement(); - builder.AddContent(0, "unrelated item"); - - // Assert - var frames = builder.GetFrames(); - Assert.Equal(4, frames.Count); - AssertFrame.Element(frames.Array[0], "my element", 3); - } - - [Fact] - public void CanNestElements() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.AddContent(0, "standalone text 1"); // 0: standalone text 1 - builder.OpenElement(0, "root"); // 1: - builder.AddContent(0, "root text 1"); // 2: root text 1 - builder.AddContent(0, "root text 2"); // 3: root text 2 - builder.OpenElement(0, "child"); // 4: - builder.AddContent(0, "child text"); // 5: child text - builder.OpenElement(0, "grandchild"); // 6: - builder.AddContent(0, "grandchild text 1"); // 7: grandchild text 1 - builder.AddContent(0, "grandchild text 2"); // 8: grandchild text 2 - builder.CloseElement(); // - builder.CloseElement(); // - builder.AddContent(0, "root text 3"); // 9: root text 3 - builder.OpenElement(0, "child 2"); // 10: - builder.CloseElement(); // - builder.CloseElement(); // - builder.AddContent(0, "standalone text 2"); // 11: standalone text 2 - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Text(frame, "standalone text 1"), - frame => AssertFrame.Element(frame, "root", 10), - frame => AssertFrame.Text(frame, "root text 1"), - frame => AssertFrame.Text(frame, "root text 2"), - frame => AssertFrame.Element(frame, "child", 5), - frame => AssertFrame.Text(frame, "child text"), - frame => AssertFrame.Element(frame, "grandchild", 3), - frame => AssertFrame.Text(frame, "grandchild text 1"), - frame => AssertFrame.Text(frame, "grandchild text 2"), - frame => AssertFrame.Text(frame, "root text 3"), - frame => AssertFrame.Element(frame, "child 2", 1), - frame => AssertFrame.Text(frame, "standalone text 2")); - } - - [Fact] - public void CanAddAttributes() - { - // Arrange - var builder = new RenderTreeBuilder(); - Action eventHandler = eventInfo => { }; - - // Act - builder.OpenElement(0, "myelement"); // 0: - builder.OpenElement(0, "child"); // 3: - builder.AddContent(0, "some text"); // 5: some text - builder.CloseElement(); // - builder.CloseElement(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "myelement", 6), - frame => AssertFrame.Attribute(frame, "attribute1", "value 1"), - frame => AssertFrame.Attribute(frame, "attribute2", "123"), - frame => AssertFrame.Element(frame, "child", 3), - frame => AssertFrame.Attribute(frame, "childevent", eventHandler), - frame => AssertFrame.Text(frame, "some text")); - } - - [Fact] - public void CanAddMultipleAttributes_AllowsNull() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "myelement"); - builder.AddMultipleAttributes(0, null); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames().AsEnumerable().ToArray(); - Assert.Collection( - frames, - frame => AssertFrame.Element(frame, "myelement", 1)); - } - - [Fact] - public void CanAddMultipleAttributes_InterspersedWithOtherAttributes() - { - // Arrange - var builder = new RenderTreeBuilder(); - Action eventHandler = eventInfo => { }; - - // Act - builder.OpenElement(0, "myelement"); - builder.AddAttribute(0, "attribute1", "value 1"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "attribute1", "test1" }, - { "attribute2", true }, - { "attribute3", eventHandler }, - }); - builder.AddAttribute(0, "ATTRIBUTE2", true); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "attribute4", "test4" }, - { "attribute5", false }, - { "attribute6", eventHandler }, - }); - - // Null or false values don't create frames of their own, but they can - // "knock out" earlier values. - builder.AddAttribute(0, "attribute6", false); - builder.AddAttribute(0, "attribute4", (string)null); - - builder.AddAttribute(0, "attribute7", "the end"); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames().AsEnumerable().ToArray(); - Assert.Collection( - frames, - frame => AssertFrame.Element(frame, "myelement", 5), - frame => AssertFrame.Attribute(frame, "attribute1", "test1"), - frame => AssertFrame.Attribute(frame, "attribute3", eventHandler), - frame => AssertFrame.Attribute(frame, "ATTRIBUTE2", true), - frame => AssertFrame.Attribute(frame, "attribute7", "the end")); - } - - [Fact] - public void CanAddMultipleAttributes_WithChildRegion() - { - // This represents bug https://github.com/aspnet/AspNetCore/issues/16570 - // If a sequence of attributes is terminated by a call to builder.OpenRegion, - // then the attribute deduplication logic wasn't working correctly - - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "myelement"); - builder.AddAttribute(0, "attribute1", "value1"); - builder.AddMultipleAttributes(1, new Dictionary() - { - { "attribute1", "value2" }, - }); - builder.OpenRegion(2); - builder.OpenElement(3, "child"); - builder.CloseElement(); - builder.CloseRegion(); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames().AsEnumerable().ToArray(); - Assert.Collection( - frames, - frame => AssertFrame.Element(frame, "myelement", 4), - frame => AssertFrame.Attribute(frame, "attribute1", "value2"), - frame => AssertFrame.Region(frame, 2, 2), - frame => AssertFrame.Element(frame, "child", 1, 3)); - } - - [Fact] - public void CanAddMultipleAttributes_DictionaryObject() - { - var attributes = new Dictionary - { - { "attribute1", "test1" }, - { "attribute2", "123" }, - { "attribute3", true }, - }; - - // Act & Assert - CanAddMultipleAttributesTest(attributes); - } - - [Fact] - public void CanAddMultipleAttributes_IReadOnlyDictionaryObject() - { - var attributes = new Dictionary - { - { "attribute1", "test1" }, - { "attribute2", "123" }, - { "attribute3", true }, - }; - - // Act & Assert - CanAddMultipleAttributesTest((IReadOnlyDictionary)attributes); - } - - [Fact] - public void CanAddMultipleAttributes_ListKvpObject() - { - var attributes = new List>() - { - new KeyValuePair("attribute1", "test1"), - new KeyValuePair("attribute2", "123"), - new KeyValuePair("attribute3", true), - }; - - // Act & Assert - CanAddMultipleAttributesTest(attributes); - } - - [Fact] - public void CanAddMultipleAttributes_ArrayKvpObject() - { - var attributes = new KeyValuePair[] - { - new KeyValuePair("attribute1", "test1"), - new KeyValuePair("attribute2", "123"), - new KeyValuePair("attribute3", true), - }; - - // Act & Assert - CanAddMultipleAttributesTest(attributes); - } - - private void CanAddMultipleAttributesTest(IEnumerable> attributes) - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "myelement"); - builder.AddMultipleAttributes(0, attributes); - builder.CloseElement(); - - // Assert - var frames = builder.GetFrames().AsEnumerable().ToArray(); - - var i = 1; - foreach (var attribute in attributes) - { - var frame = frames[i++]; - AssertFrame.Attribute(frame, attribute.Key, attribute.Value); - } - } - - [Fact] - public void CannotAddAttributeAtRoot() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.AddAttribute(0, "name", "value"); - }); - } - - [Fact] - public void CannotAddDelegateAttributeAtRoot() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.AddAttribute(0, "name", new Action(text => { })); - }); - } - - [Fact] - public void CannotAddAttributeToText() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenElement(0, "some element"); - builder.AddContent(1, "hello"); - builder.AddAttribute(2, "name", "value"); - }); - } - - [Fact] - public void CannotAddEventHandlerAttributeToText() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenElement(0, "some element"); - builder.AddContent(1, "hello"); - builder.AddAttribute(2, "name", new Action(eventInfo => { })); - }); - } - - [Fact] - public void CannotAddAttributeToRegion() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenRegion(0); - builder.AddAttribute(1, "name", "value"); - }); - } - - [Fact] - public void CannotAddAttributeToElementReferenceCapture() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenElement(0, "some element"); - builder.AddElementReferenceCapture(1, _ => { }); - builder.AddAttribute(2, "name", "value"); - }); - } - - [Fact] - public void CannotAddAttributeToComponentReferenceCapture() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenComponent(0); - builder.AddComponentReferenceCapture(1, _ => { }); - builder.AddAttribute(2, "name", "value"); - }); - } - - [Fact] - public void CanAddChildComponentsUsingGenericParam() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(10, "parent"); // 0: - builder.OpenComponent(11); // 1: - builder.CloseComponent(); // - builder.OpenComponent(14); // 4: - builder.CloseComponent(); // - builder.CloseElement(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "parent", 6), - frame => AssertFrame.Component(frame), - frame => AssertFrame.Attribute(frame, "child1attribute1", "A"), - frame => AssertFrame.Attribute(frame, "child1attribute2", "B"), - frame => AssertFrame.Component(frame), - frame => AssertFrame.Attribute(frame, "child2attribute", "C")); - } - - [Fact] - public void CanAddChildComponentsUsingTypeArgument() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - var componentType = typeof(TestComponent); - builder.OpenElement(10, "parent"); // 0: - builder.OpenComponent(11, componentType); // 1: - builder.CloseComponent(); // - builder.OpenComponent(14, componentType); // 4: - builder.CloseComponent(); // - builder.CloseElement(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "parent", 6), - frame => AssertFrame.Component(frame), - frame => AssertFrame.Attribute(frame, "child1attribute1", "A"), - frame => AssertFrame.Attribute(frame, "child1attribute2", "B"), - frame => AssertFrame.Component(frame), - frame => AssertFrame.Attribute(frame, "child2attribute", "C")); - } - - [Fact] - public void CanAddRegions() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(10, "parent"); // 0: - builder.OpenRegion(11); // 1: [region - builder.AddContent(3, "Hello"); // 2: Hello - builder.OpenRegion(4); // 3: [region - builder.OpenElement(3, "another"); // 4: - builder.CloseElement(); // - builder.CloseRegion(); // ] - builder.AddContent(6, "Goodbye"); // 5: Goodbye - builder.CloseRegion(); // ] - builder.CloseElement(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "parent", 6, 10), - frame => AssertFrame.Region(frame, 5, 11), - frame => AssertFrame.Text(frame, "Hello", 3), - frame => AssertFrame.Region(frame, 2, 4), - frame => AssertFrame.Element(frame, "another", 1, 3), - frame => AssertFrame.Text(frame, "Goodbye", 6)); - } - - [Fact] - public void CanAddFragments() - { - // Arrange - var builder = new RenderTreeBuilder(); - RenderFragment fragment = fragmentBuilder => - { - fragmentBuilder.AddContent(0, "Hello from the fragment"); - fragmentBuilder.OpenElement(1, "Fragment element"); - fragmentBuilder.AddContent(2, "Some text"); - fragmentBuilder.CloseElement(); - }; - - // Act - builder.OpenElement(10, "parent"); - builder.AddContent(11, fragment); - builder.CloseElement(); - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "parent", 5, 10), - frame => AssertFrame.Region(frame, 4, 11), - frame => AssertFrame.Text(frame, "Hello from the fragment", 0), - frame => AssertFrame.Element(frame, "Fragment element", 2, 1), - frame => AssertFrame.Text(frame, "Some text", 2)); - } - - [Fact] - public void CanAddElementReferenceCaptureInsideElement() - { - // Arrange - var builder = new RenderTreeBuilder(); - Action referenceCaptureAction = elementReference => { }; - - // Act - builder.OpenElement(0, "myelement"); // 0: - builder.AddElementReferenceCapture(2, referenceCaptureAction); // 2: # capture: referenceCaptureAction - builder.AddContent(3, "some text"); // 3: some text - builder.CloseElement(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "myelement", 4, 0), - frame => AssertFrame.Attribute(frame, "attribute2", "123", 1), - frame => AssertFrame.ElementReferenceCapture(frame, referenceCaptureAction, 2), - frame => AssertFrame.Text(frame, "some text", 3)); - } - - [Fact] - public void CannotAddElementReferenceCaptureWithNoParent() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.AddElementReferenceCapture(0, _ => { }); - }); - } - - [Fact] - public void CannotAddElementReferenceCaptureInsideComponent() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenComponent(0); - builder.AddElementReferenceCapture(1, _ => { }); - }); - } - - [Fact] - public void CannotAddElementReferenceCaptureInsideRegion() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenRegion(0); - builder.AddElementReferenceCapture(1, _ => { }); - }); - } - - [Fact] - public void CanAddMultipleReferenceCapturesToSameElement() - { - // There won't be any way of doing this from Razor because there's no known use - // case for it. However it's harder to *not* support it than to support it, and - // there's no known reason to prevent it, so here's test coverage to show it - // just works. - - // Arrange - var builder = new RenderTreeBuilder(); - Action referenceCaptureAction1 = elementReference => { }; - Action referenceCaptureAction2 = elementReference => { }; - - // Act - builder.OpenElement(0, "myelement"); - builder.AddElementReferenceCapture(0, referenceCaptureAction1); - builder.AddElementReferenceCapture(0, referenceCaptureAction2); - builder.CloseElement(); - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "myelement", 3), - frame => AssertFrame.ElementReferenceCapture(frame, referenceCaptureAction1), - frame => AssertFrame.ElementReferenceCapture(frame, referenceCaptureAction2)); - } - - [Fact] - public void CanAddComponentReferenceCaptureInsideComponent() - { - // Arrange - var builder = new RenderTreeBuilder(); - Action myAction = elementReference => { }; - - // Act - builder.OpenComponent(0); // 0: - builder.AddComponentReferenceCapture(2, myAction); // 2: # capture: myAction - builder.AddContent(3, "some text"); // 3: some text - builder.CloseComponent(); // - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 4, 0), - frame => AssertFrame.Attribute(frame, "attribute2", 123, 1), - frame => AssertFrame.ComponentReferenceCapture(frame, myAction, 2), - frame => AssertFrame.Text(frame, "some text", 3)); - } - - [Fact] - public void CannotAddComponentReferenceCaptureWithNoParent() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.AddComponentReferenceCapture(0, _ => { }); - }); - } - - [Fact] - public void CannotAddComponentReferenceCaptureInsideElement() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenElement(0, "myelement"); - builder.AddComponentReferenceCapture(1, _ => { }); - }); - } - - [Fact] - public void CannotAddComponentReferenceCaptureInsideRegion() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - Assert.Throws(() => - { - builder.OpenRegion(0); - builder.AddComponentReferenceCapture(1, _ => { }); - }); - } - - [Fact] - public void CanAddMultipleReferenceCapturesToSameComponent() - { - // There won't be any way of doing this from Razor because there's no known use - // case for it. However it's harder to *not* support it than to support it, and - // there's no known reason to prevent it, so here's test coverage to show it - // just works. - - // Arrange - var builder = new RenderTreeBuilder(); - Action referenceCaptureAction1 = elementReference => { }; - Action referenceCaptureAction2 = elementReference => { }; - - // Act - builder.OpenComponent(0); - builder.AddComponentReferenceCapture(0, referenceCaptureAction1); - builder.AddComponentReferenceCapture(0, referenceCaptureAction2); - builder.CloseComponent(); - - // Assert - Assert.Collection(builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 3), - frame => AssertFrame.ComponentReferenceCapture(frame, referenceCaptureAction1), - frame => AssertFrame.ComponentReferenceCapture(frame, referenceCaptureAction2)); - } - - [Fact] - public void CanClear() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.AddContent(0, "some text"); - builder.OpenElement(1, "elem"); - builder.AddContent(2, "more text"); - builder.CloseElement(); - builder.Clear(); - - // Assert - Assert.Empty(builder.GetFrames().AsEnumerable()); - } - - [Fact] - public void AddAttribute_Element_BoolTrue_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", true); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", true, 1)); - } - - [Fact] - public void AddAttribute_Element_BoolFalse_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", false); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AddAttribute_Component_Bool_SetsAttributeValue(bool value) - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_StringValue_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", "hi"); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", "hi", 1)); - } - - [Fact] - public void AddAttribute_Element_StringNull_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (string)null); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Theory] - [InlineData("hi")] - [InlineData(null)] - public void AddAttribute_Component_StringValue_SetsAttributeValue(string value) - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_EventHandler_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action((e) => { }); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", value); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_NullEventHandler_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (Action)null); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void AddAttribute_Element_Action_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action(() => { }); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", value); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_NullAction_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (Action)null); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - public static TheoryData> EventHandlerValues => new TheoryData> - { - null, - (e) => { }, - }; - - [Theory] - [MemberData(nameof(EventHandlerValues))] - public void AddAttribute_Component_EventHandlerValue_SetsAttributeValue(Action value) - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_EventCallback_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = new EventCallback(null, new Action(() => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback.Delegate, 1)); - } - - [Fact] - public void AddAttribute_Element_EventCallback_Default_DoesNotAddFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = default(EventCallback); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void AddAttribute_Element_EventCallbackWithReceiver_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action(() => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback, 1)); - } - - [Fact] - public void AddAttribute_Component_EventCallback_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action(() => { })); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", callback); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback, 1)); - } - - [Fact] - public void AddAttribute_Element_EventCallbackOfT_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = new EventCallback(null, new Action((s) => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback.Delegate, 1)); - } - - [Fact] - public void AddAttribute_Element_EventCallbackOfT_Default_DoesNotAddFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = default(EventCallback); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void AddAttribute_Element_EventCallbackWithReceiverOfT_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action((s) => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", new EventCallback(callback.Receiver, callback.Delegate), 1)); - } - - [Fact] - public void AddAttribute_Component_EventCallbackOfT_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action((s) => { })); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", callback); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectBoolTrue_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)true); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", true, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectBoolFalse_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)false); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AddAttribute_Component_ObjectBoolValue_SetsAttributeValue(bool value) - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", (object)value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectStringValue_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)"hi"); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", "hi", 1)); - } - - [Fact] - public void AddAttribute_Component_ObjectStringValue_SetsAttributeValue() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", (object)"hi"); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", "hi", 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventHandler_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action((e) => { }); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)value); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Component_ObjectUIEventHandleValue_SetsAttributeValue() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action((e) => { }); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", (object)value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectAction_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action(() => { }); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)value); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Component_ObjectAction_SetsAttributeValue() - { - // Arrange - var builder = new RenderTreeBuilder(); - - var value = new Action(() => { }); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", (object)value); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", value, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallback_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = new EventCallback(null, new Action(() => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback.Delegate, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallback_Default_DoesNotAddFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = default(EventCallback); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallbackWithReceiver_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action(() => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback, 1)); - } - - [Fact] - public void AddAttribute_Component_ObjectEventCallback_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action(() => { })); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Component(frame, 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallbackOfT_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = new EventCallback(null, new Action((s) => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", callback.Delegate, 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallbackOfT_Default_DoesNotAddFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var callback = default(EventCallback); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void AddAttribute_Element_ObjectEventCallbackWithReceiverOfT_AddsFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - var receiver = Mock.Of(); - var callback = new EventCallback(receiver, new Action((s) => { })); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)callback); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 2, 0), - frame => AssertFrame.Attribute(frame, "attr", new EventCallback(callback.Receiver, callback.Delegate), 1)); - } - - [Fact] - public void AddAttribute_Element_ObjectNull_IgnoresFrame() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (object)null); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => AssertFrame.Element(frame, "elem", 1, 0)); - } - - [Fact] - public void CanAddKeyToElement() - { - // Arrange - var builder = new RenderTreeBuilder(); - var keyValue = new object(); - - // Act - builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attribute before", "before value"); - builder.SetKey(keyValue); - builder.AddAttribute(2, "attribute after", "after value"); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => - { - AssertFrame.Element(frame, "elem", 3, 0); - Assert.Same(keyValue, frame.ElementKey); - }, - frame => AssertFrame.Attribute(frame, "attribute before", "before value", 1), - frame => AssertFrame.Attribute(frame, "attribute after", "after value", 2)); - } - - [Fact] - public void CanAddKeyToComponent() - { - // Arrange - var builder = new RenderTreeBuilder(); - var keyValue = new object(); - - // Act - builder.OpenComponent(0); - builder.AddAttribute(1, "param before", 123); - builder.SetKey(keyValue); - builder.AddAttribute(2, "param after", 456); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => - { - AssertFrame.Component(frame, 3, 0); - Assert.Same(keyValue, frame.ComponentKey); - }, - frame => AssertFrame.Attribute(frame, "param before", 123, 1), - frame => AssertFrame.Attribute(frame, "param after", 456, 2)); - } - - [Fact] - public void CannotAddKeyOutsideComponentOrElement_TreeRoot() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - var ex = Assert.Throws(() => - { - builder.SetKey(new object()); - }); - Assert.Equal("Cannot set a key outside the scope of a component or element.", ex.Message); - } - - [Fact] - public void CannotAddKeyOutsideComponentOrElement_RegionRoot() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act/Assert - builder.OpenElement(0, "some element"); - builder.OpenRegion(1); - var ex = Assert.Throws(() => - { - builder.SetKey(new object()); - }); - Assert.Equal($"Cannot set a key on a frame of type {RenderTreeFrameType.Region}.", ex.Message); - } - - [Fact] - public void IgnoresNullElementKey() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenElement(0, "elem"); - builder.SetKey(null); - builder.CloseElement(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => - { - AssertFrame.Element(frame, "elem", 1, 0); - Assert.Null(frame.ElementKey); - }); - } - - [Fact] - public void IgnoresNullComponentKey() - { - // Arrange - var builder = new RenderTreeBuilder(); - - // Act - builder.OpenComponent(0); - builder.SetKey(null); - builder.CloseComponent(); - - // Assert - Assert.Collection( - builder.GetFrames().AsEnumerable(), - frame => - { - AssertFrame.Component(frame, 1, 0); - Assert.Null(frame.ComponentKey); - }); - } - - [Fact] - public void ProcessDuplicateAttributes_DoesNotRemoveDuplicatesWithoutAddMultipleAttributes() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "id", "hi"); - builder.AddAttribute(0, "id", "bye"); - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 3, 0), - f => AssertFrame.Attribute(f, "id", "hi"), - f => AssertFrame.Attribute(f, "id", "bye")); - } - - - [Fact] - public void ProcessDuplicateAttributes_StopsAtFirstNonAttributeFrame_Capture() - { - // Arrange - var capture = (Action)((_) => { }); - - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "id", "hi"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.AddElementReferenceCapture(0, capture); - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 3, 0), - f => AssertFrame.Attribute(f, "id", "bye"), - f => AssertFrame.ElementReferenceCapture(f, capture)); - } - - [Fact] - public void ProcessDuplicateAttributes_StopsAtFirstNonAttributeFrame_Content() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "id", "hi"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.AddContent(0, "hey"); - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 3, 0), - f => AssertFrame.Attribute(f, "id", "bye"), - f => AssertFrame.Text(f, "hey")); - } - - [Fact] - public void ProcessDuplicateAttributes_CanRemoveDuplicateInsideElement() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "id", "hi"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 2, 0), - f => AssertFrame.Attribute(f, "id", "bye")); - } - - [Fact] - public void ProcessDuplicateAttributes_CanRemoveDuplicateInsideComponent() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenComponent(0); - builder.AddAttribute(0, "id", "hi"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.CloseComponent(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Component(f, 2, 0), - f => AssertFrame.Attribute(f, "id", "bye")); - } - - // This covers a special case we have to handle explicitly in the RTB logic. - [Fact] - public void ProcessDuplicateAttributes_SilentFrameFollowedBySameAttribute() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenComponent(0); - builder.AddAttribute(0, "id", (string)null); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.CloseComponent(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Component(f, 2, 0), - f => AssertFrame.Attribute(f, "id", "bye")); - } - - [Fact] - public void ProcessDuplicateAttributes_DoesNotRemoveDuplicatesInsideChildElement() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "id", "hi"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "id", "bye" }, - }); - builder.OpenElement(0, "strong"); - builder.AddAttribute(0, "id", "hi"); - builder.AddAttribute(0, "id", "bye"); - builder.CloseElement(); - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 5, 0), - f => AssertFrame.Attribute(f, "id", "bye"), - f => AssertFrame.Element(f, "strong", 3), - f => AssertFrame.Attribute(f, "id", "hi"), - f => AssertFrame.Attribute(f, "id", "bye")); - } - - [Fact] - public void ProcessDuplicateAttributes_CanRemoveOverwrittenAttributes() - { - // Arrange - var builder = new RenderTreeBuilder(); - builder.OpenElement(0, "div"); - builder.AddAttribute(0, "A", "hi"); - builder.AddAttribute(0, "2", new EventCallback(null, (Action)(() => { }))); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "a", null }, // Replace with null value (case-insensitive) - { "2", false }, // Replace with 'false' - { "3", "hey there" }, // Add a new value - }); - builder.AddAttribute(0, "3", "see ya"); // Overwrite value added by splat - builder.AddAttribute(0, "4", false); // Add a false value - builder.AddAttribute(0, "5", "another one"); - builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "5", null }, // overwrite value with null - { "6", new EventCallback(null, (Action)(() =>{ })) }, - }); - builder.AddAttribute(0, "6", default(EventCallback)); // Replace with a 'silent' EventCallback - builder.CloseElement(); - - // Act - var frames = builder.GetFrames().AsEnumerable(); - - // Assert - Assert.Collection( - frames, - f => AssertFrame.Element(f, "div", 2, 0), - f => AssertFrame.Attribute(f, "3", "see ya")); - } - - private class TestComponent : IComponent - { - public void Attach(RenderHandle renderHandle) { } - - public Task SetParametersAsync(ParameterView parameters) - => throw new NotImplementedException(); - } - - private class TestRenderer : Renderer - { - public TestRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance) - { - } - - public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); - - protected override void HandleException(Exception exception) - => throw new NotImplementedException(); - - protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) - => throw new NotImplementedException(); - } - } -} diff --git a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs deleted file mode 100644 index 568d2501bbb8..000000000000 --- a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs +++ /dev/null @@ -1,767 +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.Diagnostics; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Rendering -{ - public class RendererSynchronizationContextTest - { - // Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch - // failures. - public TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10); - - [Fact] - public void Post_RunsAsynchronously_WhenNotBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - var e = new ManualResetEventSlim(); - - // Act - context.Post((_) => - { - capturedThread = Thread.CurrentThread; - - e.Set(); - }, null); - - // Assert - Assert.True(e.Wait(Timeout), "timeout"); - Assert.NotSame(thread, capturedThread); - } - - [Fact] - public void Post_RunsAynchronously_WhenNotBusy_Exception() - { - // Arrange - var context = new RendererSynchronizationContext(); - - Exception exception = null; - context.UnhandledException += (sender, e) => - { - exception = (InvalidTimeZoneException)e.ExceptionObject; - }; - - // Act - context.Post((_) => - { - throw new InvalidTimeZoneException(); - }, null); - - // Assert - // - // Use another item to 'push through' the throwing one - context.Send((_) => { }, null); - Assert.NotNull(exception); - } - - [Fact] - public async Task Post_CanRunAsynchronously_WhenBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - // Act - context.Post((_) => - { - capturedThread = Thread.CurrentThread; - - e3.Set(); - }, null); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task; - - Assert.True(e3.Wait(Timeout), "timeout"); - Assert.NotSame(thread, capturedThread); - } - - [Fact] - public async Task Post_CanRunAsynchronously_CaptureExecutionContext() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // CultureInfo uses the execution context. - CultureInfo.CurrentCulture = new CultureInfo("en-GB"); - CultureInfo capturedCulture = null; - - SynchronizationContext capturedContext = null; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - // Act - SynchronizationContext original = SynchronizationContext.Current; - - try - { - SynchronizationContext.SetSynchronizationContext(context); - context.Post((_) => - { - capturedCulture = CultureInfo.CurrentCulture; - capturedContext = SynchronizationContext.Current; - e3.Set(); - }, null); - } - finally - { - SynchronizationContext.SetSynchronizationContext(original); - } - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task; - - Assert.True(e3.Wait(Timeout), "timeout"); - Assert.Same(CultureInfo.CurrentCulture, capturedCulture); - Assert.Same(context, capturedContext); - } - - [Fact] - public async Task Post_CanRunAsynchronously_WhenBusy_Exception() - { - // Arrange - var context = new RendererSynchronizationContext(); - - Exception exception = null; - context.UnhandledException += (sender, e) => - { - exception = (InvalidTimeZoneException)e.ExceptionObject; - }; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - - var task = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - // Act - context.Post((_) => - { - throw new InvalidTimeZoneException(); - }, null); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task; - - // Use another item to 'push through' the throwing one - context.Send((_) => { }, null); - Assert.NotNull(exception); - } - - [Fact] - public async Task Post_BackgroundWorkItem_CanProcessMoreItemsInline() - { - // Arrange - var context = new RendererSynchronizationContext(); - Thread capturedThread = null; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - var e4 = new ManualResetEventSlim(); - var e5 = new ManualResetEventSlim(); - var e6 = new ManualResetEventSlim(); - - // Force task2 to execute in the background - var task1 = Task.Run(() => context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null)); - - Assert.True(e1.Wait(Timeout), "timeout"); - - var task2 = Task.Run(() => - { - context.Send((_) => - { - e3.Set(); - Assert.True(e4.Wait(Timeout), "timeout"); - capturedThread = Thread.CurrentThread; - }, null); - }); - - e2.Set(); - await task1; - - Assert.True(e3.Wait(Timeout), "timeout"); - - // Act - // - // Now task2 is 'running' in the sync context. Schedule more work items - they will be - // run immediately after the second item - context.Post((_) => - { - e5.Set(); - Assert.Same(Thread.CurrentThread, capturedThread); - }, null); - context.Post((_) => - { - e6.Set(); - Assert.Same(Thread.CurrentThread, capturedThread); - }, null); - - - // Assert - e4.Set(); - await task2; - - Assert.True(e5.Wait(Timeout), "timeout"); - Assert.True(e6.Wait(Timeout), "timeout"); - } - - [Fact] - public void Post_CapturesContext() - { - // Arrange - var context = new RendererSynchronizationContext(); - - var e1 = new ManualResetEventSlim(); - - // CultureInfo uses the execution context. - CultureInfo.CurrentCulture = new CultureInfo("en-GB"); - CultureInfo capturedCulture = null; - - SynchronizationContext capturedContext = null; - - // Act - context.Post(async (_) => - { - await Task.Yield(); - - capturedCulture = CultureInfo.CurrentCulture; - capturedContext = SynchronizationContext.Current; - e1.Set(); - }, null); - - // Assert - Assert.True(e1.Wait(Timeout), "timeout"); - Assert.Same(CultureInfo.CurrentCulture, capturedCulture); - Assert.Same(context, capturedContext); - } - - [Fact] - public void Send_CanRunSynchronously() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - // Act - context.Send((_) => - { - capturedThread = Thread.CurrentThread; - }, null); - - // Assert - Assert.Same(thread, capturedThread); - } - - [Fact] - public void Send_CanRunSynchronously_Exception() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act & Assert - Assert.Throws(() => context.Send((_) => - { - throw new InvalidTimeZoneException(); - }, null)); - } - - [Fact] - public async Task Send_BlocksWhenOtherWorkRunning() - { - // Arrange - var context = new RendererSynchronizationContext(); - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - var e4 = new ManualResetEventSlim(); - - // Force task2 to execute in the background - var task1 = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - // Act - // - // Dispatch this on the background thread because otherwise it would block. - var task2 = Task.Run(() => - { - e3.Set(); - context.Send((_) => - { - e4.Set(); - }, null); - }); - - // Assert - Assert.True(e3.Wait(Timeout), "timeout"); - Assert.True(e3.IsSet); - - // Unblock the first item - e2.Set(); - await task1; - - await task2; - Assert.True(e4.IsSet); - } - - [Fact] - public void Send_CapturesContext() - { - // Arrange - var context = new RendererSynchronizationContext(); - - var e1 = new ManualResetEventSlim(); - - // CultureInfo uses the execution context. - CultureInfo.CurrentCulture = new CultureInfo("en-GB"); - CultureInfo capturedCulture = null; - - SynchronizationContext capturedContext = null; - - // Act - context.Send(async (_) => - { - await Task.Yield(); - - capturedCulture = CultureInfo.CurrentCulture; - capturedContext = SynchronizationContext.Current; - - e1.Set(); - }, null); - - // Assert - Assert.True(e1.Wait(Timeout), "timeout"); - Assert.Same(CultureInfo.CurrentCulture, capturedCulture); - Assert.Same(context, capturedContext); - } - - [Fact] - public async Task InvokeAsync_Action_CanRunSynchronously_WhenNotBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - // Act - var task = context.InvokeAsync(() => - { - capturedThread = Thread.CurrentThread; - }); - - // Assert - await task; - Assert.Same(thread, capturedThread); - } - - [Fact] - public async Task InvokeAsync_Action_CanRunAsynchronously_WhenBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task1 = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - var task2 = context.InvokeAsync(() => - { - capturedThread = Thread.CurrentThread; - - e3.Set(); - }); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task1; - - Assert.True(e3.Wait(Timeout), "timeout"); - await task2; - Assert.NotSame(thread, capturedThread); - } - - [Fact] - public async Task InvokeAsync_Action_CanRethrowExceptions() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Action)(() => - { - throw new InvalidTimeZoneException(); - })); - - // Assert - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_Action_CanReportCancellation() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Action)(() => - { - throw new OperationCanceledException(); - })); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncT_CanRunSynchronously_WhenNotBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - - // Act - var task = context.InvokeAsync(() => - { - return Thread.CurrentThread; - }); - - // Assert - Assert.Same(thread, await task); - } - - [Fact] - public async Task InvokeAsync_FuncT_CanRunAsynchronously_WhenBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task1 = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - var task2 = context.InvokeAsync(() => - { - e3.Set(); - - return Thread.CurrentThread; - }); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task1; - - Assert.True(e3.Wait(Timeout), "timeout"); - Assert.NotSame(thread, await task2); - } - - [Fact] - public async Task InvokeAsync_FuncT_CanRethrowExceptions() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Func)(() => - { - throw new InvalidTimeZoneException(); - })); - - // Assert - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncT_CanReportCancellation() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Func)(() => - { - throw new OperationCanceledException(); - })); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncTask_CanRunSynchronously_WhenNotBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - // Act - var task = context.InvokeAsync(() => - { - capturedThread = Thread.CurrentThread; - return Task.CompletedTask; - }); - - // Assert - await task; - Assert.Same(thread, capturedThread); - } - - [Fact] - public async Task InvokeAsync_FuncTask_CanRunAsynchronously_WhenBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - Thread capturedThread = null; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task1 = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - var task2 = context.InvokeAsync(() => - { - capturedThread = Thread.CurrentThread; - - e3.Set(); - return Task.CompletedTask; - }); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task1; - - Assert.True(e3.Wait(Timeout), "timeout"); - await task2; - Assert.NotSame(thread, capturedThread); - } - - [Fact] - public async Task InvokeAsync_FuncTask_CanRethrowExceptions() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync(() => - { - throw new InvalidTimeZoneException(); - }); - - // Assert - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncTask_CanReportCancellation() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync(() => - { - throw new OperationCanceledException(); - }); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncTaskT_CanRunSynchronously_WhenNotBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - - // Act - var task = context.InvokeAsync(() => - { - return Task.FromResult(Thread.CurrentThread); - }); - - // Assert - Assert.Same(thread, await task); - } - - [Fact] - public async Task InvokeAsync_FuncTaskT_CanRunAsynchronously_WhenBusy() - { - // Arrange - var context = new RendererSynchronizationContext(); - var thread = Thread.CurrentThread; - - var e1 = new ManualResetEventSlim(); - var e2 = new ManualResetEventSlim(); - var e3 = new ManualResetEventSlim(); - - var task1 = Task.Run(() => - { - context.Send((_) => - { - e1.Set(); - Assert.True(e2.Wait(Timeout), "timeout"); - }, null); - }); - - Assert.True(e1.Wait(Timeout), "timeout"); - - var task2 = context.InvokeAsync(() => - { - e3.Set(); - - return Task.FromResult(Thread.CurrentThread); - }); - - // Assert - Assert.False(e2.IsSet); - e2.Set(); // Unblock the first item - await task1; - - Assert.True(e3.Wait(Timeout), "timeout"); - Assert.NotSame(thread, await task2); - } - - [Fact] - public async Task InvokeAsync_FuncTaskT_CanRethrowExceptions() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Func>)(() => - { - throw new InvalidTimeZoneException(); - })); - - // Assert - await Assert.ThrowsAsync(async () => await task); - } - - [Fact] - public async Task InvokeAsync_FuncTaskT_CanReportCancellation() - { - // Arrange - var context = new RendererSynchronizationContext(); - - // Act - var task = context.InvokeAsync((Func>)(() => - { - throw new OperationCanceledException(); - })); - - // Assert - Assert.Equal(TaskStatus.Canceled, task.Status); - await Assert.ThrowsAsync(async () => await task); - } - } -} diff --git a/src/Components/Components/test/Rendering/TestArrayPool.cs b/src/Components/Components/test/Rendering/TestArrayPool.cs deleted file mode 100644 index c5335a6b64a8..000000000000 --- a/src/Components/Components/test/Rendering/TestArrayPool.cs +++ /dev/null @@ -1,23 +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.Buffers; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - internal class TestArrayPool : ArrayPool - { - public override T[] Rent(int minimumLength) - { - return new T[minimumLength]; - } - - public List ReturnedBuffers = new List(); - - public override void Return(T[] array, bool clearArray = false) - { - ReturnedBuffers.Add(array); - } - } -} diff --git a/src/Components/Components/test/RouteViewTest.cs b/src/Components/Components/test/RouteViewTest.cs deleted file mode 100644 index 05b1c8b20f4d..000000000000 --- a/src/Components/Components/test/RouteViewTest.cs +++ /dev/null @@ -1,209 +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.Linq; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Test.Helpers; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test -{ - public class RouteViewTest - { - private readonly TestRenderer _renderer; - private readonly RouteView _routeViewComponent; - private readonly int _routeViewComponentId; - - public RouteViewTest() - { - _renderer = new TestRenderer(); - _routeViewComponent = new RouteView(); - _routeViewComponentId = _renderer.AssignRootComponentId(_routeViewComponent); - } - - [Fact] - public void ThrowsIfNoRouteDataSupplied() - { - var ex = Assert.Throws(() => - { - // Throws synchronously, so no need to await - _ = _routeViewComponent.SetParametersAsync(ParameterView.Empty); - }); - - - Assert.Equal($"The {nameof(RouteView)} component requires a non-null value for the parameter {nameof(RouteView.RouteData)}.", ex.Message); - } - - [Fact] - public void RendersPageInsideLayoutView() - { - // Arrange - var routeParams = new Dictionary - { - { nameof(ComponentWithLayout.Message), "Test message" } - }; - var routeData = new RouteData(typeof(ComponentWithLayout), routeParams); - - // Act - _renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(RouteView.RouteData), routeData }, - }))); - - // Assert: RouteView renders LayoutView - var batch = _renderer.Batches.Single(); - var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable(); - Assert.Collection(routeViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 3, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(TestLayout), sequence: 1), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2)); - - // Assert: LayoutView renders TestLayout - var layoutViewComponentId = batch.GetComponentFrames().Single().ComponentId; - var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(layoutViewComponentId).AsEnumerable(); - Assert.Collection(layoutViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 2, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1)); - - // Assert: TestLayout renders page - var testLayoutComponentId = batch.GetComponentFrames().Single().ComponentId; - var testLayoutFrames = _renderer.GetCurrentRenderTreeFrames(testLayoutComponentId).AsEnumerable(); - Assert.Collection(testLayoutFrames, - frame => AssertFrame.Text(frame, "Layout starts here", sequence: 0), - frame => AssertFrame.Region(frame, subtreeLength: 3), - frame => AssertFrame.Component(frame, sequence: 0, subtreeLength: 2), - frame => AssertFrame.Attribute(frame, nameof(ComponentWithLayout.Message), "Test message", sequence: 1), - frame => AssertFrame.Text(frame, "Layout ends here", sequence: 2)); - - // Assert: page itself is rendered, having received parameters from the original route data - var pageComponentId = batch.GetComponentFrames().Single().ComponentId; - var pageFrames = _renderer.GetCurrentRenderTreeFrames(pageComponentId).AsEnumerable(); - Assert.Collection(pageFrames, - frame => AssertFrame.Text(frame, "Hello from the page with message 'Test message'", sequence: 0)); - - // Assert: nothing else was rendered - Assert.Equal(4, batch.DiffsInOrder.Count); - } - - [Fact] - public void UsesDefaultLayoutIfNoneSetOnPage() - { - // Arrange - var routeParams = new Dictionary(); - var routeData = new RouteData(typeof(ComponentWithoutLayout), routeParams); - - // Act - _renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(RouteView.RouteData), routeData }, - { nameof(RouteView.DefaultLayout), typeof(OtherLayout) }, - }))); - - // Assert: uses default layout - // Not asserting about what else gets rendered as that's covered by other tests - var batch = _renderer.Batches.Single(); - var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable(); - Assert.Collection(routeViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 3, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(OtherLayout), sequence: 1), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2)); - } - - [Fact] - public void UsesNoLayoutIfNoneSetOnPageAndNoDefaultSet() - { - // Arrange - var routeParams = new Dictionary(); - var routeData = new RouteData(typeof(ComponentWithoutLayout), routeParams); - - // Act - _renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(RouteView.RouteData), routeData }, - }))); - - // Assert: uses no layout - // Not asserting about what else gets rendered as that's covered by other tests - var batch = _renderer.Batches.Single(); - var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable(); - Assert.Collection(routeViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 3, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)null, sequence: 1), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2)); - } - - [Fact] - public void PageLayoutSupersedesDefaultLayout() - { - // Arrange - var routeParams = new Dictionary(); - var routeData = new RouteData(typeof(ComponentWithLayout), routeParams); - - // Act - _renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary - { - { nameof(RouteView.RouteData), routeData }, - { nameof(RouteView.DefaultLayout), typeof(OtherLayout) }, - }))); - - // Assert: uses layout specified by page - // Not asserting about what else gets rendered as that's covered by other tests - var batch = _renderer.Batches.Single(); - var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable(); - Assert.Collection(routeViewFrames, - frame => AssertFrame.Component(frame, subtreeLength: 3, sequence: 0), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(TestLayout), sequence: 1), - frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2)); - } - - private class ComponentWithoutLayout : AutoRenderComponent - { - [Parameter] public string Message { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, $"Hello from the page with message '{Message}'"); - } - } - - [Layout(typeof(TestLayout))] - private class ComponentWithLayout : AutoRenderComponent - { - [Parameter] public string Message { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, $"Hello from the page with message '{Message}'"); - } - } - - private class TestLayout : AutoRenderComponent - { - [Parameter] - public RenderFragment Body { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "Layout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "Layout ends here"); - } - } - - private class OtherLayout : AutoRenderComponent - { - [Parameter] - public RenderFragment Body { get; set; } - - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddContent(0, "OtherLayout starts here"); - builder.AddContent(1, Body); - builder.AddContent(2, "OtherLayout ends here"); - } - } - } -} diff --git a/src/Components/Components/test/Routing/RouteConstraintTest.cs b/src/Components/Components/test/Routing/RouteConstraintTest.cs deleted file mode 100644 index 34889f03dd46..000000000000 --- a/src/Components/Components/test/Routing/RouteConstraintTest.cs +++ /dev/null @@ -1,36 +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.Routing -{ - public class RouteConstraintTest - { - [Fact] - public void Parse_CreatesDifferentConstraints_ForDifferentKinds() - { - // Arrange - var original = RouteConstraint.Parse("ignore", "ignore", "int"); - - // Act - var another = RouteConstraint.Parse("ignore", "ignore", "guid"); - - // Assert - Assert.NotSame(original, another); - } - - [Fact] - public void Parse_CachesCreatedConstraint_ForSameKind() - { - // Arrange - var original = RouteConstraint.Parse("ignore", "ignore", "int"); - - // Act - var another = RouteConstraint.Parse("ignore", "ignore", "int"); - - // Assert - Assert.Same(original, another); - } - } -} diff --git a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs b/src/Components/Components/test/Routing/RouteTableFactoryTests.cs deleted file mode 100644 index 92bea90d7998..000000000000 --- a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs +++ /dev/null @@ -1,504 +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.Linq; -using Microsoft.AspNetCore.Components.Routing; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Test.Routing -{ - public class RouteTableFactoryTests - { - [Fact] - public void CanCacheRouteTable() - { - // Arrange - var routes1 = RouteTableFactory.Create(new[] { GetType().Assembly, }); - - // Act - var routes2 = RouteTableFactory.Create(new[] { GetType().Assembly, }); - - // Assert - Assert.Same(routes1, routes2); - } - - [Fact] - public void CanCacheRouteTableWithDifferentAssembliesAndOrder() - { - // Arrange - var routes1 = RouteTableFactory.Create(new[] { typeof(object).Assembly, GetType().Assembly, }); - - // Act - var routes2 = RouteTableFactory.Create(new[] { GetType().Assembly, typeof(object).Assembly, }); - - // Assert - Assert.Same(routes1, routes2); - } - - [Fact] - public void DoesNotCacheRouteTableForDifferentAssemblies() - { - // Arrange - var routes1 = RouteTableFactory.Create(new[] { GetType().Assembly, }); - - // Act - var routes2 = RouteTableFactory.Create(new[] { GetType().Assembly, typeof(object).Assembly, }); - - // Assert - Assert.NotSame(routes1, routes2); - } - - [Fact] - public void CanDiscoverRoute() - { - // Arrange & Act - var routes = RouteTableFactory.Create(new[] { typeof(MyComponent), }); - - // Assert - Assert.Equal("Test1", Assert.Single(routes.Routes).Template.TemplateText); - } - - [Route("Test1")] - private class MyComponent : ComponentBase - { - } - - [Fact] - public void CanDiscoverRoutes_WithInheritance() - { - // Arrange & Act - var routes = RouteTableFactory.Create(new[] { typeof(MyComponent), typeof(MyInheritedComponent), }); - - // Assert - Assert.Collection( - routes.Routes.OrderBy(r => r.Template.TemplateText), - r => Assert.Equal("Test1", r.Template.TemplateText), - r => Assert.Equal("Test2", r.Template.TemplateText)); - } - - [Route("Test2")] - private class MyInheritedComponent : MyComponent - { - } - - [Fact] - public void CanMatchRootTemplate() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/").Build(); - var context = new RouteContext("/"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - } - - [Fact] - public void CanMatchLiteralTemplate() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/literal").Build(); - var context = new RouteContext("/literal/"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - } - - [Fact] - public void CanMatchTemplateWithMultipleLiterals() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/some/awesome/route/").Build(); - var context = new RouteContext("/some/awesome/route"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - } - - [Fact] - public void RouteMatchingIsCaseInsensitive() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/some/AWESOME/route/").Build(); - var context = new RouteContext("/Some/awesome/RouTe"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - } - - [Fact] - public void CanMatchEncodedSegments() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/some/ünicõdē/🛣/").Build(); - var context = new RouteContext("/some/%C3%BCnic%C3%B5d%C4%93/%F0%9F%9B%A3"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - } - - [Fact] - public void DoesNotMatchIfSegmentsDontMatch() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/some/AWESOME/route/").Build(); - var context = new RouteContext("/some/brilliant/route"); - - // Act - routeTable.Route(context); - - // Assert - Assert.Null(context.Handler); - } - - [Theory] - [InlineData("/{value:bool}", "/maybe")] - [InlineData("/{value:datetime}", "/1955-01-32")] - [InlineData("/{value:decimal}", "/hello")] - [InlineData("/{value:double}", "/0.1.2")] - [InlineData("/{value:float}", "/0.1.2")] - [InlineData("/{value:guid}", "/not-a-guid")] - [InlineData("/{value:int}", "/3.141")] - [InlineData("/{value:long}", "/3.141")] - public void DoesNotMatchIfConstraintDoesNotMatch(string template, string contextUrl) - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute(template).Build(); - var context = new RouteContext(contextUrl); - - // Act - routeTable.Route(context); - - // Assert - Assert.Null(context.Handler); - } - - [Theory] - [InlineData("/some")] - [InlineData("/some/awesome/route/with/extra/segments")] - public void DoesNotMatchIfDifferentNumberOfSegments(string path) - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/some/awesome/route/").Build(); - var context = new RouteContext(path); - - // Act - routeTable.Route(context); - - // Assert - Assert.Null(context.Handler); - } - - [Theory] - [InlineData("/value1", "value1")] - [InlineData("/value2/", "value2")] - [InlineData("/d%C3%A9j%C3%A0%20vu", "déjà vu")] - [InlineData("/d%C3%A9j%C3%A0%20vu/", "déjà vu")] - [InlineData("/d%C3%A9j%C3%A0+vu", "déjà+vu")] - public void CanMatchParameterTemplate(string path, string expectedValue) - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/{parameter}").Build(); - var context = new RouteContext(path); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - Assert.Single(context.Parameters, p => p.Key == "parameter" && (string)p.Value == expectedValue); - } - - [Fact] - public void CanMatchTemplateWithMultipleParameters() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/{some}/awesome/{route}/").Build(); - var context = new RouteContext("/an/awesome/path"); - - var expectedParameters = new Dictionary - { - ["some"] = "an", - ["route"] = "path" - }; - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - Assert.Equal(expectedParameters, context.Parameters); - } - - public static IEnumerable CanMatchParameterWithConstraintCases() => new object[][] - { - new object[] { "/{value:bool}", "/true", true }, - new object[] { "/{value:bool}", "/false", false }, - new object[] { "/{value:datetime}", "/1955-01-30", new DateTime(1955, 1, 30) }, - new object[] { "/{value:decimal}", "/5.3", 5.3m }, - new object[] { "/{value:double}", "/0.1", 0.1d }, - new object[] { "/{value:float}", "/0.1", 0.1f }, - new object[] { "/{value:guid}", "/1FCEF085-884F-416E-B0A1-71B15F3E206B", Guid.Parse("1FCEF085-884F-416E-B0A1-71B15F3E206B") }, - new object[] { "/{value:int}", "/123", 123 }, - new object[] { "/{value:int}", "/-123", -123}, - new object[] { "/{value:long}", "/9223372036854775807", long.MaxValue }, - new object[] { "/{value:long}", $"/-9223372036854775808", long.MinValue }, - }; - - [Theory] - [MemberData(nameof(CanMatchParameterWithConstraintCases))] - public void CanMatchParameterWithConstraint(string template, string contextUrl, object convertedValue) - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute(template).Build(); - var context = new RouteContext(contextUrl); - - // Act - routeTable.Route(context); - - // Assert - if (context.Handler == null) - { - // Make it easier to track down failing tests when using MemberData - throw new InvalidOperationException($"Failed to match template '{template}'."); - } - Assert.Equal(context.Parameters, new Dictionary - { - { "value", convertedValue } - }); - } - - [Fact] - public void CanMatchSegmentWithMultipleConstraints() - { - // Arrange - var routeTable = new TestRouteTableBuilder().AddRoute("/{value:double:int}/").Build(); - var context = new RouteContext("/15"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - Assert.Equal(context.Parameters, new Dictionary - { - { "value", 15 } // Final constraint's convertedValue is used - }); - } - - [Fact] - public void PrefersLiteralTemplateOverTemplateWithParameters() - { - // Arrange - var routeTable = new TestRouteTableBuilder() - .AddRoute("/an/awesome/path", typeof(TestHandler1)) - .AddRoute("/{some}/awesome/{route}/", typeof(TestHandler2)) - .Build(); - var context = new RouteContext("/an/awesome/path"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - Assert.Null(context.Parameters); - } - - [Fact] - public void PrefersShorterRoutesOverLongerRoutes() - { - // Arrange & Act - var handler = typeof(int); - var routeTable = new TestRouteTableBuilder() - .AddRoute("/an/awesome/path") - .AddRoute("/an/awesome/", handler).Build(); - - // Act - Assert.Equal("an/awesome", routeTable.Routes[0].Template.TemplateText); - } - - [Fact] - public void PrefersMoreConstraintsOverFewer() - { - // Arrange - var routeTable = new TestRouteTableBuilder() - .AddRoute("/products/{id}") - .AddRoute("/products/{id:int}").Build(); - var context = new RouteContext("/products/456"); - - // Act - routeTable.Route(context); - - // Assert - Assert.NotNull(context.Handler); - Assert.Equal(context.Parameters, new Dictionary - { - { "id", 456 } - }); - } - - [Fact] - public void ProducesAStableOrderForNonAmbiguousRoutes() - { - // Arrange & Act - var handler = typeof(int); - var routeTable = new TestRouteTableBuilder() - .AddRoute("/an/awesome/", handler) - .AddRoute("/a/brilliant/").Build(); - - // Act - Assert.Equal("a/brilliant", routeTable.Routes[0].Template.TemplateText); - } - - [Fact] - public void DoesNotThrowIfStableSortComparesRouteWithItself() - { - // Test for https://github.com/aspnet/AspNetCore/issues/13313 - // Arrange & Act - var builder = new TestRouteTableBuilder(); - builder.AddRoute("r16"); - builder.AddRoute("r05"); - builder.AddRoute("r09"); - builder.AddRoute("r00"); - builder.AddRoute("r13"); - builder.AddRoute("r02"); - builder.AddRoute("r03"); - builder.AddRoute("r10"); - builder.AddRoute("r15"); - builder.AddRoute("r14"); - builder.AddRoute("r12"); - builder.AddRoute("r07"); - builder.AddRoute("r11"); - builder.AddRoute("r08"); - builder.AddRoute("r06"); - builder.AddRoute("r04"); - builder.AddRoute("r01"); - - var routeTable = builder.Build(); - - // Act - Assert.Equal(17, routeTable.Routes.Length); - for (var i = 0; i < 17; i++) - { - var templateText = "r" + i.ToString().PadLeft(2, '0'); - Assert.Equal(templateText, routeTable.Routes[i].Template.TemplateText); - } - } - - [Theory] - [InlineData("/literal", "/Literal/")] - [InlineData("/{parameter}", "/{parameter}/")] - [InlineData("/literal/{parameter}", "/Literal/{something}")] - [InlineData("/{parameter}/literal/{something}", "{param}/Literal/{else}")] - public void DetectsAmbiguousRoutes(string left, string right) - { - // Arrange - var expectedMessage = $@"The following routes are ambiguous: -'{left.Trim('/')}' in '{typeof(object).FullName}' -'{right.Trim('/')}' in '{typeof(object).FullName}' -"; - // Act - var exception = Assert.Throws(() => new TestRouteTableBuilder() - .AddRoute(left) - .AddRoute(right).Build()); - - Assert.Equal(expectedMessage, exception.Message); - } - - [Fact] - public void SuppliesNullForUnusedHandlerParameters() - { - // Arrange - var routeTable = new TestRouteTableBuilder() - .AddRoute("/", typeof(TestHandler1)) - .AddRoute("/products/{param1:int}", typeof(TestHandler1)) - .AddRoute("/products/{param2}/{PaRam1}", typeof(TestHandler1)) - .AddRoute("/{unrelated}", typeof(TestHandler2)) - .Build(); - var context = new RouteContext("/products/456"); - - // Act - routeTable.Route(context); - - // Assert - Assert.Collection(routeTable.Routes, - route => - { - Assert.Same(typeof(TestHandler1), route.Handler); - Assert.Equal("/", route.Template.TemplateText); - Assert.Equal(new[] { "param1", "param2" }, route.UnusedRouteParameterNames); - }, - route => - { - Assert.Same(typeof(TestHandler2), route.Handler); - Assert.Equal("{unrelated}", route.Template.TemplateText); - Assert.Equal(Array.Empty(), route.UnusedRouteParameterNames); - }, - route => - { - Assert.Same(typeof(TestHandler1), route.Handler); - Assert.Equal("products/{param1:int}", route.Template.TemplateText); - Assert.Equal(new[] { "param2" }, route.UnusedRouteParameterNames); - }, - route => - { - Assert.Same(typeof(TestHandler1), route.Handler); - Assert.Equal("products/{param2}/{PaRam1}", route.Template.TemplateText); - Assert.Equal(Array.Empty(), route.UnusedRouteParameterNames); - }); - Assert.Same(typeof(TestHandler1), context.Handler); - Assert.Equal(new Dictionary - { - { "param1", 456 }, - { "param2", null }, - }, context.Parameters); - } - - private class TestRouteTableBuilder - { - IList<(string Template, Type Handler)> _routeTemplates = new List<(string, Type)>(); - Type _handler = typeof(object); - - public TestRouteTableBuilder AddRoute(string template, Type handler = null) - { - _routeTemplates.Add((template, handler ?? _handler)); - return this; - } - - public RouteTable Build() - { - try - { - var templatesByHandler = _routeTemplates - .GroupBy(rt => rt.Handler) - .ToDictionary(group => group.Key, group => group.Select(g => g.Template).ToArray()); - return RouteTableFactory.Create(templatesByHandler); - } - catch (InvalidOperationException ex) when (ex.InnerException is InvalidOperationException) - { - // ToArray() will wrap our exception in its own. - throw ex.InnerException; - } - } - } - - class TestHandler1 { } - class TestHandler2 { } - } -} diff --git a/src/Components/Components/test/Routing/TemplateParserTests.cs b/src/Components/Components/test/Routing/TemplateParserTests.cs deleted file mode 100644 index 752963f52da9..000000000000 --- a/src/Components/Components/test/Routing/TemplateParserTests.cs +++ /dev/null @@ -1,187 +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.Linq; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Routing -{ - public class TemplateParserTests - { - [Fact] - public void Parse_SingleLiteral() - { - // Arrange - var expected = new ExpectedTemplateBuilder().Literal("awesome"); - - // Act - var actual = TemplateParser.ParseTemplate("awesome"); - - // Assert - Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance); - } - - [Fact] - public void Parse_SingleParameter() - { - // Arrange - var template = "{p}"; - - var expected = new ExpectedTemplateBuilder().Parameter("p"); - - // Act - var actual = TemplateParser.ParseTemplate(template); - - // Assert - Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance); - } - - [Fact] - public void Parse_MultipleLiterals() - { - // Arrange - var template = "awesome/cool/super"; - - var expected = new ExpectedTemplateBuilder().Literal("awesome").Literal("cool").Literal("super"); - - // Act - var actual = TemplateParser.ParseTemplate(template); - - // Assert - Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance); - } - - [Fact] - public void Parse_MultipleParameters() - { - // Arrange - var template = "{p1}/{p2}/{p3}"; - - var expected = new ExpectedTemplateBuilder().Parameter("p1").Parameter("p2").Parameter("p3"); - - // Act - var actual = TemplateParser.ParseTemplate(template); - - // Assert - Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance); - } - - [Fact] - public void InvalidTemplate_WithRepeatedParameter() - { - var ex = Assert.Throws( - () => TemplateParser.ParseTemplate("{p1}/literal/{p1}")); - - var expectedMessage = "Invalid template '{p1}/literal/{p1}'. The parameter 'Microsoft.AspNetCore.Components.Routing.TemplateSegment' appears multiple times."; - - Assert.Equal(expectedMessage, ex.Message); - } - - [Theory] - [InlineData("p}", "Invalid template 'p}'. Missing '{' in parameter segment 'p}'.")] - [InlineData("{p", "Invalid template '{p'. Missing '}' in parameter segment '{p'.")] - [InlineData("Literal/p}", "Invalid template 'Literal/p}'. Missing '{' in parameter segment 'p}'.")] - [InlineData("Literal/{p", "Invalid template 'Literal/{p'. Missing '}' in parameter segment '{p'.")] - [InlineData("p}/Literal", "Invalid template 'p}/Literal'. Missing '{' in parameter segment 'p}'.")] - [InlineData("{p/Literal", "Invalid template '{p/Literal'. Missing '}' in parameter segment '{p'.")] - [InlineData("Another/p}/Literal", "Invalid template 'Another/p}/Literal'. Missing '{' in parameter segment 'p}'.")] - [InlineData("Another/{p/Literal", "Invalid template 'Another/{p/Literal'. Missing '}' in parameter segment '{p'.")] - - public void InvalidTemplate_WithMismatchedBraces(string template, string expectedMessage) - { - var ex = Assert.Throws( - () => TemplateParser.ParseTemplate(template)); - - Assert.Equal(expectedMessage, ex.Message); - } - - [Theory] - [InlineData("{*}", "Invalid template '{*}'. The character '*' in parameter segment '{*}' is not allowed.")] - [InlineData("{?}", "Invalid template '{?}'. The character '?' in parameter segment '{?}' is not allowed.")] - [InlineData("{{}", "Invalid template '{{}'. The character '{' in parameter segment '{{}' is not allowed.")] - [InlineData("{}}", "Invalid template '{}}'. The character '}' in parameter segment '{}}' is not allowed.")] - [InlineData("{=}", "Invalid template '{=}'. The character '=' in parameter segment '{=}' is not allowed.")] - [InlineData("{.}", "Invalid template '{.}'. The character '.' in parameter segment '{.}' is not allowed.")] - public void ParseRouteParameter_ThrowsIf_ParameterContainsSpecialCharacters(string template, string expectedMessage) - { - // Act & Assert - var ex = Assert.Throws(() => TemplateParser.ParseTemplate(template)); - - Assert.Equal(expectedMessage, ex.Message); - } - - [Fact] - public void InvalidTemplate_InvalidParameterNameWithEmptyNameThrows() - { - var ex = Assert.Throws(() => TemplateParser.ParseTemplate("{a}/{}/{z}")); - - var expectedMessage = "Invalid template '{a}/{}/{z}'. Empty parameter name in segment '{}' is not allowed."; - - Assert.Equal(expectedMessage, ex.Message); - } - - [Fact] - public void InvalidTemplate_ConsecutiveSeparatorsSlashSlashThrows() - { - var ex = Assert.Throws(() => TemplateParser.ParseTemplate("{a}//{z}")); - - var expectedMessage = "Invalid template '{a}//{z}'. Empty segments are not allowed."; - - Assert.Equal(expectedMessage, ex.Message); - } - - private class ExpectedTemplateBuilder - { - public IList Segments { get; set; } = new List(); - - public ExpectedTemplateBuilder Literal(string value) - { - Segments.Add(new TemplateSegment("testtemplate", value, isParameter: false)); - return this; - } - - public ExpectedTemplateBuilder Parameter(string value) - { - Segments.Add(new TemplateSegment("testtemplate", value, isParameter: true)); - return this; - } - - public RouteTemplate Build() => new RouteTemplate(string.Join('/', Segments), Segments.ToArray()); - - public static implicit operator RouteTemplate(ExpectedTemplateBuilder builder) => builder.Build(); - } - - private class RouteTemplateTestComparer : IEqualityComparer - { - public static RouteTemplateTestComparer Instance { get; } = new RouteTemplateTestComparer(); - - public bool Equals(RouteTemplate x, RouteTemplate y) - { - if (x.Segments.Length != y.Segments.Length) - { - return false; - } - - for (var i = 0; i < x.Segments.Length; i++) - { - var xSegment = x.Segments[i]; - var ySegment = y.Segments[i]; - if (xSegment.IsParameter != ySegment.IsParameter) - { - return false; - } - if (!string.Equals(xSegment.Value, ySegment.Value, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - } - - return true; - } - - public int GetHashCode(RouteTemplate obj) => 0; - } - } -} diff --git a/src/Components/Components/test/StackObjectPoolTest.cs b/src/Components/Components/test/StackObjectPoolTest.cs deleted file mode 100644 index 33b9becc0549..000000000000 --- a/src/Components/Components/test/StackObjectPoolTest.cs +++ /dev/null @@ -1,123 +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 Xunit; - -namespace Microsoft.AspNetCore.Components.RenderTree -{ - public class StackObjectPoolTest - { - [Fact] - public void CanGetInstances() - { - // Arrange - var stackObjectPool = new StackObjectPool(10, () => new object()); - - // Act - var instance1 = stackObjectPool.Get(); - var instance2 = stackObjectPool.Get(); - - // Assert - Assert.NotNull(instance1); - Assert.NotNull(instance2); - Assert.NotSame(instance1, instance2); - } - - [Fact] - public void CanReturnInstances() - { - // Arrange - var stackObjectPool = new StackObjectPool(10, () => new object()); - var instance1 = stackObjectPool.Get(); - var instance2 = stackObjectPool.Get(); - - // Act/Assert - // No exception means success - stackObjectPool.Return(instance2); - stackObjectPool.Return(instance1); - } - - [Fact] - public void ReusesInstancesInPoolUpToCapacity() - { - // Arrange - var stackObjectPool = new StackObjectPool(10, () => new object()); - var instance1 = stackObjectPool.Get(); - var instance2 = stackObjectPool.Get(); - stackObjectPool.Return(instance2); - stackObjectPool.Return(instance1); - - // Act - var instance1b = stackObjectPool.Get(); - var instance2b = stackObjectPool.Get(); - var instance3 = stackObjectPool.Get(); - - // Assert - Assert.Same(instance1, instance1b); - Assert.Same(instance2, instance2b); - Assert.NotNull(instance3); - Assert.NotSame(instance1, instance3); - Assert.NotSame(instance2, instance3); - } - - [Fact] - public void SuppliesTransientInstancesWhenExceedingCapacity() - { - // Arrange - var stackObjectPool = new StackObjectPool(1, () => new object()); - - // Act 1: Returns distinct instances beyond capacity - var instance1 = stackObjectPool.Get(); - var instance2 = stackObjectPool.Get(); - var instance3 = stackObjectPool.Get(); - Assert.NotNull(instance1); - Assert.NotNull(instance2); - Assert.NotNull(instance3); - Assert.Equal(3, new[] { instance1, instance2, instance3 }.Distinct().Count()); - - // Act 2: Can return all instances, including transient ones - stackObjectPool.Return(instance3); - stackObjectPool.Return(instance2); - stackObjectPool.Return(instance1); - - // Act 3: Reuses only the non-transient instances - var instance1b = stackObjectPool.Get(); - var instance2b = stackObjectPool.Get(); - Assert.Same(instance1, instance1b); - Assert.NotSame(instance2b, instance2); - Assert.Equal(4, new[] { instance1, instance2, instance3, instance2b }.Distinct().Count()); - } - - [Fact] - public void CannotReturnWhenEmpty() - { - // Arrange - var stackObjectPool = new StackObjectPool(10, () => new object()); - - // Act/Assert - var ex = Assert.Throws(() => - { - stackObjectPool.Return(new object()); - }); - Assert.Equal("There are no outstanding instances to return.", ex.Message); - } - - [Fact] - public void CannotReturnMismatchingTrackedItem() - { - // Arrange - var stackObjectPool = new StackObjectPool(10, () => new object()); - var instance1 = stackObjectPool.Get(); - var instance2 = stackObjectPool.Get(); - - // Act/Assert - var ex = Assert.Throws(() => - { - stackObjectPool.Return(instance1); - }); - Assert.Equal("Attempting to return wrong pooled instance. Get/Return calls must form a stack.", ex.Message); - } - } -} diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf deleted file mode 100644 index 7e09eeea25ce..000000000000 --- a/src/Components/ComponentsNoDeps.slnf +++ /dev/null @@ -1,45 +0,0 @@ -{ - "solution": { - "path": "Components.sln", - "projects": [ - "Analyzers\\src\\Microsoft.AspNetCore.Components.Analyzers.csproj", - "Analyzers\\test\\Microsoft.AspNetCore.Components.Analyzers.Tests.csproj", - "Authorization\\src\\Microsoft.AspNetCore.Components.Authorization.csproj", - "Authorization\\test\\Microsoft.AspNetCore.Components.Authorization.Tests.csproj", - "Blazor\\Blazor\\src\\Microsoft.AspNetCore.Blazor.csproj", - "Blazor\\Blazor\\test\\Microsoft.AspNetCore.Blazor.Tests.csproj", - "Blazor\\Build\\src\\Microsoft.AspNetCore.Blazor.Build.csproj", - "Blazor\\Build\\test\\Microsoft.AspNetCore.Blazor.Build.Tests.csproj", - "Blazor\\DevServer\\src\\Microsoft.AspNetCore.Blazor.DevServer.csproj", - "Blazor\\Http\\src\\Microsoft.AspNetCore.Blazor.HttpClient.csproj", - "Blazor\\Http\\test\\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", - "Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj", - "Blazor\\Server\\src\\Microsoft.AspNetCore.Blazor.Server.csproj", - "Blazor\\Validation\\src\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", - "Blazor\\Validation\\test\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", - "Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", - "Blazor\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj", - "Blazor\\testassets\\MonoSanityClient\\MonoSanityClient.csproj", - "Blazor\\testassets\\MonoSanity\\MonoSanity.csproj", - "Blazor\\testassets\\StandaloneApp\\StandaloneApp.csproj", - "Components\\perf\\Microsoft.AspNetCore.Components.Performance.csproj", - "Components\\src\\Microsoft.AspNetCore.Components.csproj", - "Components\\test\\Microsoft.AspNetCore.Components.Tests.csproj", - "Forms\\src\\Microsoft.AspNetCore.Components.Forms.csproj", - "Forms\\test\\Microsoft.AspNetCore.Components.Forms.Tests.csproj", - "Ignitor\\src\\Ignitor.csproj", - "Ignitor\\test\\Ignitor.Test.csproj", - "Samples\\BlazorServerApp\\BlazorServerApp.csproj", - "Server\\src\\Microsoft.AspNetCore.Components.Server.csproj", - "Server\\test\\Microsoft.AspNetCore.Components.Server.Tests.csproj", - "Web\\src\\Microsoft.AspNetCore.Components.Web.csproj", - "Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj", - "benchmarkapps\\Wasm.Performance\\Driver\\Wasm.Performance.Driver.csproj", - "benchmarkapps\\Wasm.Performance\\TestApp\\Wasm.Performance.TestApp.csproj", - "test\\E2ETest\\Microsoft.AspNetCore.Components.E2ETests.csproj", - "test\\testassets\\BasicTestApp\\BasicTestApp.csproj", - "test\\testassets\\TestContentPackage\\TestContentPackage.csproj", - "test\\testassets\\TestServer\\Components.TestServer.csproj" - ] - } -} \ No newline at end of file diff --git a/src/Components/Directory.Build.props b/src/Components/Directory.Build.props index ef310ac60dcd..227faf5fc038 100644 --- a/src/Components/Directory.Build.props +++ b/src/Components/Directory.Build.props @@ -14,7 +14,7 @@ - 3.1.0 + 3.1.2 $(MSBuildThisFileDirectory)Shared\ diff --git a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.csproj b/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.csproj deleted file mode 100644 index cc3fcfda2760..000000000000 --- a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - - - - - - - - - - - diff --git a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netcoreapp.cs b/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netcoreapp.cs deleted file mode 100644 index 4674ff0fb4e2..000000000000 --- a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netcoreapp.cs +++ /dev/null @@ -1,75 +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.Forms -{ - public partial class DataAnnotationsValidator : Microsoft.AspNetCore.Components.ComponentBase - { - public DataAnnotationsValidator() { } - protected override void OnInitialized() { } - } - public sealed partial class EditContext - { - public EditContext(object model) { } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public event System.EventHandler OnFieldChanged { add { } remove { } } - public event System.EventHandler OnValidationRequested { add { } remove { } } - public event System.EventHandler OnValidationStateChanged { add { } remove { } } - public Microsoft.AspNetCore.Components.Forms.FieldIdentifier Field(string fieldName) { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages() { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages(Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages(System.Linq.Expressions.Expression> accessor) { throw null; } - public bool IsModified() { throw null; } - public bool IsModified(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } - public bool IsModified(System.Linq.Expressions.Expression> accessor) { throw null; } - public void MarkAsUnmodified() { } - public void MarkAsUnmodified(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void NotifyFieldChanged(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void NotifyValidationStateChanged() { } - public bool Validate() { throw null; } - } - public static partial class EditContextDataAnnotationsExtensions - { - public static Microsoft.AspNetCore.Components.Forms.EditContext AddDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext) { throw null; } - } - public sealed partial class FieldChangedEventArgs : System.EventArgs - { - public FieldChangedEventArgs(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct FieldIdentifier : System.IEquatable - { - private readonly object _dummy; - public FieldIdentifier(object model, string fieldName) { throw null; } - public string FieldName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public static Microsoft.AspNetCore.Components.Forms.FieldIdentifier Create(System.Linq.Expressions.Expression> accessor) { throw null; } - public bool Equals(Microsoft.AspNetCore.Components.Forms.FieldIdentifier otherIdentifier) { throw null; } - public override bool Equals(object obj) { throw null; } - public override int GetHashCode() { throw null; } - } - public sealed partial class ValidationMessageStore - { - public ValidationMessageStore(Microsoft.AspNetCore.Components.Forms.EditContext editContext) { } - public System.Collections.Generic.IEnumerable this[Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier] { get { throw null; } } - public System.Collections.Generic.IEnumerable this[System.Linq.Expressions.Expression> accessor] { get { throw null; } } - public void Add(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier, System.Collections.Generic.IEnumerable messages) { } - public void Add(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier, string message) { } - public void Add(System.Linq.Expressions.Expression> accessor, System.Collections.Generic.IEnumerable messages) { } - public void Add(System.Linq.Expressions.Expression> accessor, string message) { } - public void Clear() { } - public void Clear(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void Clear(System.Linq.Expressions.Expression> accessor) { } - } - public sealed partial class ValidationRequestedEventArgs : System.EventArgs - { - public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationRequestedEventArgs Empty; - public ValidationRequestedEventArgs() { } - } - public sealed partial class ValidationStateChangedEventArgs : System.EventArgs - { - public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationStateChangedEventArgs Empty; - public ValidationStateChangedEventArgs() { } - } -} diff --git a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netstandard2.0.cs b/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netstandard2.0.cs deleted file mode 100644 index 4674ff0fb4e2..000000000000 --- a/src/Components/Forms/ref/Microsoft.AspNetCore.Components.Forms.netstandard2.0.cs +++ /dev/null @@ -1,75 +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.Forms -{ - public partial class DataAnnotationsValidator : Microsoft.AspNetCore.Components.ComponentBase - { - public DataAnnotationsValidator() { } - protected override void OnInitialized() { } - } - public sealed partial class EditContext - { - public EditContext(object model) { } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public event System.EventHandler OnFieldChanged { add { } remove { } } - public event System.EventHandler OnValidationRequested { add { } remove { } } - public event System.EventHandler OnValidationStateChanged { add { } remove { } } - public Microsoft.AspNetCore.Components.Forms.FieldIdentifier Field(string fieldName) { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages() { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages(Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } - public System.Collections.Generic.IEnumerable GetValidationMessages(System.Linq.Expressions.Expression> accessor) { throw null; } - public bool IsModified() { throw null; } - public bool IsModified(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } - public bool IsModified(System.Linq.Expressions.Expression> accessor) { throw null; } - public void MarkAsUnmodified() { } - public void MarkAsUnmodified(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void NotifyFieldChanged(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void NotifyValidationStateChanged() { } - public bool Validate() { throw null; } - } - public static partial class EditContextDataAnnotationsExtensions - { - public static Microsoft.AspNetCore.Components.Forms.EditContext AddDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext) { throw null; } - } - public sealed partial class FieldChangedEventArgs : System.EventArgs - { - public FieldChangedEventArgs(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct FieldIdentifier : System.IEquatable - { - private readonly object _dummy; - public FieldIdentifier(object model, string fieldName) { throw null; } - public string FieldName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public static Microsoft.AspNetCore.Components.Forms.FieldIdentifier Create(System.Linq.Expressions.Expression> accessor) { throw null; } - public bool Equals(Microsoft.AspNetCore.Components.Forms.FieldIdentifier otherIdentifier) { throw null; } - public override bool Equals(object obj) { throw null; } - public override int GetHashCode() { throw null; } - } - public sealed partial class ValidationMessageStore - { - public ValidationMessageStore(Microsoft.AspNetCore.Components.Forms.EditContext editContext) { } - public System.Collections.Generic.IEnumerable this[Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier] { get { throw null; } } - public System.Collections.Generic.IEnumerable this[System.Linq.Expressions.Expression> accessor] { get { throw null; } } - public void Add(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier, System.Collections.Generic.IEnumerable messages) { } - public void Add(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier, string message) { } - public void Add(System.Linq.Expressions.Expression> accessor, System.Collections.Generic.IEnumerable messages) { } - public void Add(System.Linq.Expressions.Expression> accessor, string message) { } - public void Clear() { } - public void Clear(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { } - public void Clear(System.Linq.Expressions.Expression> accessor) { } - } - public sealed partial class ValidationRequestedEventArgs : System.EventArgs - { - public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationRequestedEventArgs Empty; - public ValidationRequestedEventArgs() { } - } - public sealed partial class ValidationStateChangedEventArgs : System.EventArgs - { - public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationStateChangedEventArgs Empty; - public ValidationStateChangedEventArgs() { } - } -} diff --git a/src/Components/Forms/src/DataAnnotationsValidator.cs b/src/Components/Forms/src/DataAnnotationsValidator.cs deleted file mode 100644 index 63696d2c797a..000000000000 --- a/src/Components/Forms/src/DataAnnotationsValidator.cs +++ /dev/null @@ -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 System; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Adds Data Annotations validation support to an . - /// - public class DataAnnotationsValidator : ComponentBase - { - [CascadingParameter] EditContext CurrentEditContext { get; set; } - - /// - protected override void OnInitialized() - { - if (CurrentEditContext == null) - { - throw new InvalidOperationException($"{nameof(DataAnnotationsValidator)} requires a cascading " + - $"parameter of type {nameof(EditContext)}. For example, you can use {nameof(DataAnnotationsValidator)} " + - $"inside an EditForm."); - } - - CurrentEditContext.AddDataAnnotationsValidation(); - } - } -} diff --git a/src/Components/Forms/src/EditContext.cs b/src/Components/Forms/src/EditContext.cs deleted file mode 100644 index caaf677c3744..000000000000 --- a/src/Components/Forms/src/EditContext.cs +++ /dev/null @@ -1,210 +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.Linq; -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Holds metadata related to a data editing process, such as flags to indicate which - /// fields have been modified and the current set of validation messages. - /// - public sealed class EditContext - { - // Note that EditContext tracks state for any FieldIdentifier you give to it, plus - // the underlying storage is sparse. As such, none of the APIs have a "field not found" - // error state. If you give us an unrecognized FieldIdentifier, that just means we - // didn't yet track any state for it, so we behave as if it's in the default state - // (valid and unmodified). - private readonly Dictionary _fieldStates = new Dictionary(); - - /// - /// Constructs an instance of . - /// - /// The model object for the . This object should hold the data being edited, for example as a set of properties. - public EditContext(object model) - { - // The only reason we disallow null is because you'd almost always want one, and if you - // really don't, you can pass an empty object then ignore it. Ensuring it's nonnull - // simplifies things for all consumers of EditContext. - Model = model ?? throw new ArgumentNullException(nameof(model)); - } - - /// - /// An event that is raised when a field value changes. - /// - public event EventHandler OnFieldChanged; - - /// - /// An event that is raised when validation is requested. - /// - public event EventHandler OnValidationRequested; - - /// - /// An event that is raised when validation state has changed. - /// - public event EventHandler OnValidationStateChanged; - - /// - /// Supplies a corresponding to a specified field name - /// on this 's . - /// - /// The name of the editable field. - /// A corresponding to a specified field name on this 's . - public FieldIdentifier Field(string fieldName) - => new FieldIdentifier(Model, fieldName); - - /// - /// Gets the model object for this . - /// - public object Model { get; } - - /// - /// Signals that the value for the specified field has changed. - /// - /// Identifies the field whose value has been changed. - public void NotifyFieldChanged(in FieldIdentifier fieldIdentifier) - { - GetFieldState(fieldIdentifier, ensureExists: true).IsModified = true; - OnFieldChanged?.Invoke(this, new FieldChangedEventArgs(fieldIdentifier)); - } - - /// - /// Signals that some aspect of validation state has changed. - /// - public void NotifyValidationStateChanged() - { - OnValidationStateChanged?.Invoke(this, ValidationStateChangedEventArgs.Empty); - } - - /// - /// Clears any modification flag that may be tracked for the specified field. - /// - /// Identifies the field whose modification flag (if any) should be cleared. - public void MarkAsUnmodified(in FieldIdentifier fieldIdentifier) - { - if (_fieldStates.TryGetValue(fieldIdentifier, out var state)) - { - state.IsModified = false; - } - } - - /// - /// Clears all modification flags within this . - /// - public void MarkAsUnmodified() - { - foreach (var state in _fieldStates) - { - state.Value.IsModified = false; - } - } - - /// - /// Determines whether any of the fields in this have been modified. - /// - /// True if any of the fields in this have been modified; otherwise false. - public bool IsModified() - { - // If necessary, we could consider caching the overall "is modified" state and only recomputing - // when there's a call to NotifyFieldModified/NotifyFieldUnmodified - foreach (var state in _fieldStates) - { - if (state.Value.IsModified) - { - return true; - } - } - - return false; - } - - /// - /// Gets the current validation messages across all fields. - /// - /// This method does not perform validation itself. It only returns messages determined by previous validation actions. - /// - /// The current validation messages. - public IEnumerable GetValidationMessages() - { - // Since we're only enumerating the fields for which we have a non-null state, the cost of this grows - // based on how many fields have been modified or have associated validation messages - foreach (var state in _fieldStates) - { - foreach (var message in state.Value.GetValidationMessages()) - { - yield return message; - } - } - } - - /// - /// Gets the current validation messages for the specified field. - /// - /// This method does not perform validation itself. It only returns messages determined by previous validation actions. - /// - /// Identifies the field whose current validation messages should be returned. - /// The current validation messages for the specified field. - public IEnumerable GetValidationMessages(FieldIdentifier fieldIdentifier) - { - if (_fieldStates.TryGetValue(fieldIdentifier, out var state)) - { - foreach (var message in state.GetValidationMessages()) - { - yield return message; - } - } - } - - /// - /// Gets the current validation messages for the specified field. - /// - /// This method does not perform validation itself. It only returns messages determined by previous validation actions. - /// - /// Identifies the field whose current validation messages should be returned. - /// The current validation messages for the specified field. - public IEnumerable GetValidationMessages(Expression> accessor) - => GetValidationMessages(FieldIdentifier.Create(accessor)); - - /// - /// Determines whether the specified fields in this has been modified. - /// - /// True if the field has been modified; otherwise false. - public bool IsModified(in FieldIdentifier fieldIdentifier) - => _fieldStates.TryGetValue(fieldIdentifier, out var state) - ? state.IsModified - : false; - - /// - /// Determines whether the specified fields in this has been modified. - /// - /// Identifies the field whose current validation messages should be returned. - /// True if the field has been modified; otherwise false. - public bool IsModified(Expression> accessor) - => IsModified(FieldIdentifier.Create(accessor)); - - /// - /// Validates this . - /// - /// True if there are no validation messages after validation; otherwise false. - public bool Validate() - { - OnValidationRequested?.Invoke(this, ValidationRequestedEventArgs.Empty); - return !GetValidationMessages().Any(); - } - - internal FieldState GetFieldState(in FieldIdentifier fieldIdentifier, bool ensureExists) - { - if (!_fieldStates.TryGetValue(fieldIdentifier, out var state) && ensureExists) - { - state = new FieldState(fieldIdentifier); - _fieldStates.Add(fieldIdentifier, state); - } - - return state; - } - } -} diff --git a/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs b/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs deleted file mode 100644 index e7f9d5f15507..000000000000 --- a/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs +++ /dev/null @@ -1,107 +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.Concurrent; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Reflection; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Extension methods to add DataAnnotations validation to an . - /// - public static class EditContextDataAnnotationsExtensions - { - private static ConcurrentDictionary<(Type ModelType, string FieldName), PropertyInfo> _propertyInfoCache - = new ConcurrentDictionary<(Type, string), PropertyInfo>(); - - /// - /// Adds DataAnnotations validation support to the . - /// - /// The . - public static EditContext AddDataAnnotationsValidation(this EditContext editContext) - { - if (editContext == null) - { - throw new ArgumentNullException(nameof(editContext)); - } - - var messages = new ValidationMessageStore(editContext); - - // Perform object-level validation on request - editContext.OnValidationRequested += - (sender, eventArgs) => ValidateModel((EditContext)sender, messages); - - // Perform per-field validation on each field edit - editContext.OnFieldChanged += - (sender, eventArgs) => ValidateField(editContext, messages, eventArgs.FieldIdentifier); - - return editContext; - } - - private static void ValidateModel(EditContext editContext, ValidationMessageStore messages) - { - var validationContext = new ValidationContext(editContext.Model); - var validationResults = new List(); - Validator.TryValidateObject(editContext.Model, validationContext, validationResults, true); - - // Transfer results to the ValidationMessageStore - messages.Clear(); - foreach (var validationResult in validationResults) - { - if (!validationResult.MemberNames.Any()) - { - messages.Add(new FieldIdentifier(editContext.Model, fieldName: string.Empty), validationResult.ErrorMessage); - continue; - } - - foreach (var memberName in validationResult.MemberNames) - { - messages.Add(editContext.Field(memberName), validationResult.ErrorMessage); - } - } - - editContext.NotifyValidationStateChanged(); - } - - private static void ValidateField(EditContext editContext, ValidationMessageStore messages, in FieldIdentifier fieldIdentifier) - { - if (TryGetValidatableProperty(fieldIdentifier, out var propertyInfo)) - { - var propertyValue = propertyInfo.GetValue(fieldIdentifier.Model); - var validationContext = new ValidationContext(fieldIdentifier.Model) - { - MemberName = propertyInfo.Name - }; - var results = new List(); - - Validator.TryValidateProperty(propertyValue, validationContext, results); - messages.Clear(fieldIdentifier); - messages.Add(fieldIdentifier, results.Select(result => result.ErrorMessage)); - - // We have to notify even if there were no messages before and are still no messages now, - // because the "state" that changed might be the completion of some async validation task - editContext.NotifyValidationStateChanged(); - } - } - - private static bool TryGetValidatableProperty(in FieldIdentifier fieldIdentifier, out PropertyInfo propertyInfo) - { - var cacheKey = (ModelType: fieldIdentifier.Model.GetType(), fieldIdentifier.FieldName); - if (!_propertyInfoCache.TryGetValue(cacheKey, out propertyInfo)) - { - // DataAnnotations only validates public properties, so that's all we'll look for - // If we can't find it, cache 'null' so we don't have to try again next time - propertyInfo = cacheKey.ModelType.GetProperty(cacheKey.FieldName); - - // No need to lock, because it doesn't matter if we write the same value twice - _propertyInfoCache[cacheKey] = propertyInfo; - } - - return propertyInfo != null; - } - } -} diff --git a/src/Components/Forms/src/FieldChangedEventArgs.cs b/src/Components/Forms/src/FieldChangedEventArgs.cs deleted file mode 100644 index 780a91a01d35..000000000000 --- a/src/Components/Forms/src/FieldChangedEventArgs.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Provides information about the event. - /// - public sealed class FieldChangedEventArgs : EventArgs - { - /// - /// Creates a new instance of . - /// - /// The - public FieldChangedEventArgs(in FieldIdentifier fieldIdentifier) - { - FieldIdentifier = fieldIdentifier; - } - - /// - /// Identifies the field whose value has changed. - /// - public FieldIdentifier FieldIdentifier { get; } - } -} diff --git a/src/Components/Forms/src/FieldIdentifier.cs b/src/Components/Forms/src/FieldIdentifier.cs deleted file mode 100644 index 1c2c923d38bf..000000000000 --- a/src/Components/Forms/src/FieldIdentifier.cs +++ /dev/null @@ -1,121 +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.Expressions; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Uniquely identifies a single field that can be edited. This may correspond to a property on a - /// model object, or can be any other named value. - /// - public readonly struct FieldIdentifier : IEquatable - { - /// - /// Initializes a new instance of the structure. - /// - /// An expression that identifies an object member. - /// The field . - public static FieldIdentifier Create(Expression> accessor) - { - if (accessor == null) - { - throw new ArgumentNullException(nameof(accessor)); - } - - ParseAccessor(accessor, out var model, out var fieldName); - return new FieldIdentifier(model, fieldName); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The object that owns the field. - /// The name of the editable field. - public FieldIdentifier(object model, string fieldName) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - - if (model.GetType().IsValueType) - { - throw new ArgumentException("The model must be a reference-typed object.", nameof(model)); - } - - Model = model; - - // Note that we do allow an empty string. This is used by some validation systems - // as a place to store object-level (not per-property) messages. - FieldName = fieldName ?? throw new ArgumentNullException(nameof(fieldName)); - } - - /// - /// Gets the object that owns the editable field. - /// - public object Model { get; } - - /// - /// Gets the name of the editable field. - /// - public string FieldName { get; } - - /// - public override int GetHashCode() - => (Model, FieldName).GetHashCode(); - - /// - public override bool Equals(object obj) - => obj is FieldIdentifier otherIdentifier - && Equals(otherIdentifier); - - /// - public bool Equals(FieldIdentifier otherIdentifier) - { - return - otherIdentifier.Model == Model && - string.Equals(otherIdentifier.FieldName, FieldName, StringComparison.Ordinal); - } - - private static void ParseAccessor(Expression> accessor, out object model, out string fieldName) - { - var accessorBody = accessor.Body; - - // Unwrap casts to object - if (accessorBody is UnaryExpression unaryExpression - && unaryExpression.NodeType == ExpressionType.Convert - && unaryExpression.Type == typeof(object)) - { - accessorBody = unaryExpression.Operand; - } - - if (!(accessorBody is MemberExpression memberExpression)) - { - throw new ArgumentException($"The provided expression contains a {accessorBody.GetType().Name} which is not supported. {nameof(FieldIdentifier)} only supports simple member accessors (fields, properties) of an object."); - } - - // Identify the field name. We don't mind whether it's a property or field, or even something else. - fieldName = memberExpression.Member.Name; - - // Get a reference to the model object - // i.e., given an value like "(something).MemberName", determine the runtime value of "(something)", - switch (memberExpression.Expression) - { - case ConstantExpression constantExpression: - model = constantExpression.Value; - break; - default: - // It would be great to cache this somehow, but it's unclear there's a reasonable way to do - // so, given that it embeds captured values such as "this". We could consider special-casing - // for "() => something.Member" and building a cache keyed by "something.GetType()" with values - // of type Func so we can cheaply map from "something" to "something.Member". - var modelLambda = Expression.Lambda(memberExpression.Expression); - var modelLambdaCompiled = (Func)modelLambda.Compile(); - model = modelLambdaCompiled(); - break; - } - } - } -} diff --git a/src/Components/Forms/src/FieldState.cs b/src/Components/Forms/src/FieldState.cs deleted file mode 100644 index 3a8d1f0eb36c..000000000000 --- a/src/Components/Forms/src/FieldState.cs +++ /dev/null @@ -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.Collections.Generic; - -namespace Microsoft.AspNetCore.Components.Forms -{ - internal class FieldState - { - private readonly FieldIdentifier _fieldIdentifier; - - // We track which ValidationMessageStore instances have a nonempty set of messages for this field so that - // we can quickly evaluate the list of messages for the field without having to query all stores. This is - // relevant because each validation component may define its own message store, so there might be as many - // stores are there are fields or UI elements. - private HashSet _validationMessageStores; - - public FieldState(FieldIdentifier fieldIdentifier) - { - _fieldIdentifier = fieldIdentifier; - } - - public bool IsModified { get; set; } - - public IEnumerable GetValidationMessages() - { - if (_validationMessageStores != null) - { - foreach (var store in _validationMessageStores) - { - foreach (var message in store[_fieldIdentifier]) - { - yield return message; - } - } - } - } - - public void AssociateWithValidationMessageStore(ValidationMessageStore validationMessageStore) - { - if (_validationMessageStores == null) - { - _validationMessageStores = new HashSet(); - } - - _validationMessageStores.Add(validationMessageStore); - } - - public void DissociateFromValidationMessageStore(ValidationMessageStore validationMessageStore) - => _validationMessageStores?.Remove(validationMessageStore); - } -} diff --git a/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj b/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj deleted file mode 100644 index d338f21000d3..000000000000 --- a/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - netstandard2.0;$(DefaultNetCoreTargetFramework) - $(DefaultNetCoreTargetFramework) - true - Forms and validation support for Blazor applications. - true - true - - - - - - - - - - - diff --git a/src/Components/Forms/src/ValidationMessageStore.cs b/src/Components/Forms/src/ValidationMessageStore.cs deleted file mode 100644 index a8b0664bec90..000000000000 --- a/src/Components/Forms/src/ValidationMessageStore.cs +++ /dev/null @@ -1,128 +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.Linq; -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Holds validation messages for an . - /// - public sealed class ValidationMessageStore - { - private readonly EditContext _editContext; - private readonly Dictionary> _messages = new Dictionary>(); - - /// - /// Creates an instance of . - /// - /// The with which this store should be associated. - public ValidationMessageStore(EditContext editContext) - { - _editContext = editContext ?? throw new ArgumentNullException(nameof(editContext)); - } - - /// - /// Adds a validation message for the specified field. - /// - /// The identifier for the field. - /// The validation message. - public void Add(in FieldIdentifier fieldIdentifier, string message) - => GetOrCreateMessagesListForField(fieldIdentifier).Add(message); - - /// - /// Adds a validation message for the specified field. - /// - /// Identifies the field for which to add the message. - /// The validation message. - public void Add(Expression> accessor, string message) - => Add(FieldIdentifier.Create(accessor), message); - - /// - /// Adds the messages from the specified collection for the specified field. - /// - /// The identifier for the field. - /// The validation messages to be added. - public void Add(in FieldIdentifier fieldIdentifier, IEnumerable messages) - => GetOrCreateMessagesListForField(fieldIdentifier).AddRange(messages); - - /// - /// Adds the messages from the specified collection for the specified field. - /// - /// Identifies the field for which to add the messages. - /// The validation messages to be added. - public void Add(Expression> accessor, IEnumerable messages) - => Add(FieldIdentifier.Create(accessor), messages); - - /// - /// Gets the validation messages within this for the specified field. - /// - /// To get the validation messages across all validation message stores, use instead - /// - /// The identifier for the field. - /// The validation messages for the specified field within this . - public IEnumerable this[FieldIdentifier fieldIdentifier] - => _messages.TryGetValue(fieldIdentifier, out var messages) ? messages : Enumerable.Empty(); - - /// - /// Gets the validation messages within this for the specified field. - /// - /// To get the validation messages across all validation message stores, use instead - /// - /// The identifier for the field. - /// The validation messages for the specified field within this . - public IEnumerable this[Expression> accessor] - => this[FieldIdentifier.Create(accessor)]; - - /// - /// Removes all messages within this . - /// - public void Clear() - { - foreach (var fieldIdentifier in _messages.Keys) - { - DissociateFromField(fieldIdentifier); - } - - _messages.Clear(); - } - - /// - /// Removes all messages within this for the specified field. - /// - /// Identifies the field for which to remove the messages. - public void Clear(Expression> accessor) - => Clear(FieldIdentifier.Create(accessor)); - - /// - /// Removes all messages within this for the specified field. - /// - /// The identifier for the field. - public void Clear(in FieldIdentifier fieldIdentifier) - { - DissociateFromField(fieldIdentifier); - _messages.Remove(fieldIdentifier); - } - - private List GetOrCreateMessagesListForField(in FieldIdentifier fieldIdentifier) - { - if (!_messages.TryGetValue(fieldIdentifier, out var messagesForField)) - { - messagesForField = new List(); - _messages.Add(fieldIdentifier, messagesForField); - AssociateWithField(fieldIdentifier); - } - - return messagesForField; - } - - private void AssociateWithField(in FieldIdentifier fieldIdentifier) - => _editContext.GetFieldState(fieldIdentifier, ensureExists: true).AssociateWithValidationMessageStore(this); - - private void DissociateFromField(in FieldIdentifier fieldIdentifier) - => _editContext.GetFieldState(fieldIdentifier, ensureExists: false)?.DissociateFromValidationMessageStore(this); - } -} diff --git a/src/Components/Forms/src/ValidationRequestedEventArgs.cs b/src/Components/Forms/src/ValidationRequestedEventArgs.cs deleted file mode 100644 index 52efde8de529..000000000000 --- a/src/Components/Forms/src/ValidationRequestedEventArgs.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Provides information about the event. - /// - public sealed class ValidationRequestedEventArgs : EventArgs - { - /// - /// Gets a shared empty instance of . - /// - public static new readonly ValidationRequestedEventArgs Empty = new ValidationRequestedEventArgs(); - - /// - /// Creates a new instance of . - /// - public ValidationRequestedEventArgs() - { - } - } -} diff --git a/src/Components/Forms/src/ValidationStateChangedEventArgs.cs b/src/Components/Forms/src/ValidationStateChangedEventArgs.cs deleted file mode 100644 index fd8dbb8d69c8..000000000000 --- a/src/Components/Forms/src/ValidationStateChangedEventArgs.cs +++ /dev/null @@ -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; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Provides information about the event. - /// - public sealed class ValidationStateChangedEventArgs : EventArgs - { - /// - /// Gets a shared empty instance of . - /// - public new static readonly ValidationStateChangedEventArgs Empty = new ValidationStateChangedEventArgs(); - - /// - /// Creates a new instance of - /// - public ValidationStateChangedEventArgs() - { - } - } -} diff --git a/src/Components/Forms/test/EditContextDataAnnotationsExtensionsTest.cs b/src/Components/Forms/test/EditContextDataAnnotationsExtensionsTest.cs deleted file mode 100644 index bb7837e2f08f..000000000000 --- a/src/Components/Forms/test/EditContextDataAnnotationsExtensionsTest.cs +++ /dev/null @@ -1,170 +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.ComponentModel.DataAnnotations; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Forms -{ - public class EditContextDataAnnotationsExtensionsTest - { - [Fact] - public void CannotUseNullEditContext() - { - var editContext = (EditContext)null; - var ex = Assert.Throws(() => editContext.AddDataAnnotationsValidation()); - Assert.Equal("editContext", ex.ParamName); - } - - [Fact] - public void ReturnsEditContextForChaining() - { - var editContext = new EditContext(new object()); - var returnValue = editContext.AddDataAnnotationsValidation(); - Assert.Same(editContext, returnValue); - } - - [Fact] - public void GetsValidationMessagesFromDataAnnotations() - { - // Arrange - var model = new TestModel { IntFrom1To100 = 101 }; - var editContext = new EditContext(model).AddDataAnnotationsValidation(); - - // Act - var isValid = editContext.Validate(); - - // Assert - Assert.False(isValid); - - Assert.Equal(new string[] - { - "RequiredString:required", - "IntFrom1To100:range" - }, - editContext.GetValidationMessages()); - - Assert.Equal(new string[] { "RequiredString:required" }, - editContext.GetValidationMessages(editContext.Field(nameof(TestModel.RequiredString)))); - - // This shows we're including non-[Required] properties in the validation results, i.e, - // that we're correctly passing "validateAllProperties: true" to DataAnnotations - Assert.Equal(new string[] { "IntFrom1To100:range" }, - editContext.GetValidationMessages(editContext.Field(nameof(TestModel.IntFrom1To100)))); - } - - [Fact] - public void ClearsExistingValidationMessagesOnFurtherRuns() - { - // Arrange - var model = new TestModel { IntFrom1To100 = 101 }; - var editContext = new EditContext(model).AddDataAnnotationsValidation(); - - // Act/Assert 1: Initially invalid - Assert.False(editContext.Validate()); - - // Act/Assert 2: Can become valid - model.RequiredString = "Hello"; - model.IntFrom1To100 = 100; - Assert.True(editContext.Validate()); - } - - [Fact] - public void NotifiesValidationStateChangedAfterObjectValidation() - { - // Arrange - var model = new TestModel { IntFrom1To100 = 101 }; - var editContext = new EditContext(model).AddDataAnnotationsValidation(); - var onValidationStateChangedCount = 0; - editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; - - // Act/Assert 1: Notifies after invalid results - Assert.False(editContext.Validate()); - Assert.Equal(1, onValidationStateChangedCount); - - // Act/Assert 2: Notifies after valid results - model.RequiredString = "Hello"; - model.IntFrom1To100 = 100; - Assert.True(editContext.Validate()); - Assert.Equal(2, onValidationStateChangedCount); - - // Act/Assert 3: Notifies even if results haven't changed. Later we might change the - // logic to track the previous results and compare with the new ones, but that's just - // an optimization. It's legal to notify regardless. - Assert.True(editContext.Validate()); - Assert.Equal(3, onValidationStateChangedCount); - } - - [Fact] - public void PerformsPerPropertyValidationOnFieldChange() - { - // Arrange - var model = new TestModel { IntFrom1To100 = 101 }; - var independentTopLevelModel = new object(); // To show we can validate things on any model, not just the top-level one - var editContext = new EditContext(independentTopLevelModel).AddDataAnnotationsValidation(); - var onValidationStateChangedCount = 0; - var requiredStringIdentifier = new FieldIdentifier(model, nameof(TestModel.RequiredString)); - var intFrom1To100Identifier = new FieldIdentifier(model, nameof(TestModel.IntFrom1To100)); - editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; - - // Act/Assert 1: Notify about RequiredString - // Only RequiredString gets validated, even though IntFrom1To100 also holds an invalid value - editContext.NotifyFieldChanged(requiredStringIdentifier); - Assert.Equal(1, onValidationStateChangedCount); - Assert.Equal(new[] { "RequiredString:required" }, editContext.GetValidationMessages()); - - // Act/Assert 2: Fix RequiredString, but only notify about IntFrom1To100 - // Only IntFrom1To100 gets validated; messages for RequiredString are left unchanged - model.RequiredString = "This string is very cool and very legal"; - editContext.NotifyFieldChanged(intFrom1To100Identifier); - Assert.Equal(2, onValidationStateChangedCount); - Assert.Equal(new string[] - { - "RequiredString:required", - "IntFrom1To100:range" - }, - editContext.GetValidationMessages()); - - // Act/Assert 3: Notify about RequiredString - editContext.NotifyFieldChanged(requiredStringIdentifier); - Assert.Equal(3, onValidationStateChangedCount); - Assert.Equal(new[] { "IntFrom1To100:range" }, editContext.GetValidationMessages()); - } - - [Theory] - [InlineData(nameof(TestModel.ThisWillNotBeValidatedBecauseItIsAField))] - [InlineData(nameof(TestModel.ThisWillNotBeValidatedBecauseItIsInternal))] - [InlineData("ThisWillNotBeValidatedBecauseItIsPrivate")] - [InlineData("This does not correspond to anything")] - [InlineData("")] - public void IgnoresFieldChangesThatDoNotCorrespondToAValidatableProperty(string fieldName) - { - // Arrange - var editContext = new EditContext(new TestModel()).AddDataAnnotationsValidation(); - var onValidationStateChangedCount = 0; - editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; - - // Act/Assert: Ignores field changes that don't correspond to a validatable property - editContext.NotifyFieldChanged(editContext.Field(fieldName)); - Assert.Equal(0, onValidationStateChangedCount); - - // Act/Assert: For sanity, observe that we would have validated if it was a validatable property - editContext.NotifyFieldChanged(editContext.Field(nameof(TestModel.RequiredString))); - Assert.Equal(1, onValidationStateChangedCount); - } - - class TestModel - { - [Required(ErrorMessage = "RequiredString:required")] public string RequiredString { get; set; } - - [Range(1, 100, ErrorMessage = "IntFrom1To100:range")] public int IntFrom1To100 { get; set; } - -#pragma warning disable 649 - [Required] public string ThisWillNotBeValidatedBecauseItIsAField; - [Required] string ThisWillNotBeValidatedBecauseItIsPrivate { get; set; } - [Required] internal string ThisWillNotBeValidatedBecauseItIsInternal { get; set; } -#pragma warning restore 649 - } - } -} diff --git a/src/Components/Forms/test/EditContextTest.cs b/src/Components/Forms/test/EditContextTest.cs deleted file mode 100644 index 5c8e7af36e1d..000000000000 --- a/src/Components/Forms/test/EditContextTest.cs +++ /dev/null @@ -1,240 +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 Xunit; - -namespace Microsoft.AspNetCore.Components.Forms -{ - public class EditContextTest - { - [Fact] - public void CannotUseNullModel() - { - var ex = Assert.Throws(() => new EditContext(null)); - Assert.Equal("model", ex.ParamName); - } - - [Fact] - public void CanGetModel() - { - var model = new object(); - var editContext = new EditContext(model); - Assert.Same(model, editContext.Model); - } - - [Fact] - public void CanConstructFieldIdentifiersForRootModel() - { - // Arrange/Act - var model = new object(); - var editContext = new EditContext(model); - var fieldIdentifier = editContext.Field("testFieldName"); - - // Assert - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal("testFieldName", fieldIdentifier.FieldName); - } - - [Fact] - public void IsInitiallyUnmodified() - { - var editContext = new EditContext(new object()); - Assert.False(editContext.IsModified()); - } - - [Fact] - public void TracksFieldsAsModifiedWhenValueChanged() - { - // Arrange - var editContext = new EditContext(new object()); - var fieldOnThisModel1 = editContext.Field("field1"); - var fieldOnThisModel2 = editContext.Field("field2"); - var fieldOnOtherModel = new FieldIdentifier(new object(), "field on other model"); - - // Act - editContext.NotifyFieldChanged(fieldOnThisModel1); - editContext.NotifyFieldChanged(fieldOnOtherModel); - - // Assert - Assert.True(editContext.IsModified()); - Assert.True(editContext.IsModified(fieldOnThisModel1)); - Assert.False(editContext.IsModified(fieldOnThisModel2)); - Assert.True(editContext.IsModified(fieldOnOtherModel)); - } - - [Fact] - public void CanClearIndividualModifications() - { - // Arrange - var editContext = new EditContext(new object()); - var fieldThatWasModified = editContext.Field("field1"); - var fieldThatRemainsModified = editContext.Field("field2"); - var fieldThatWasNeverModified = editContext.Field("field that was never modified"); - editContext.NotifyFieldChanged(fieldThatWasModified); - editContext.NotifyFieldChanged(fieldThatRemainsModified); - - // Act - editContext.MarkAsUnmodified(fieldThatWasModified); - editContext.MarkAsUnmodified(fieldThatWasNeverModified); - - // Assert - Assert.True(editContext.IsModified()); - Assert.False(editContext.IsModified(fieldThatWasModified)); - Assert.True(editContext.IsModified(fieldThatRemainsModified)); - Assert.False(editContext.IsModified(fieldThatWasNeverModified)); - } - - [Fact] - public void CanClearAllModifications() - { - // Arrange - var editContext = new EditContext(new object()); - var field1 = editContext.Field("field1"); - var field2 = editContext.Field("field2"); - editContext.NotifyFieldChanged(field1); - editContext.NotifyFieldChanged(field2); - - // Act - editContext.MarkAsUnmodified(); - - // Assert - Assert.False(editContext.IsModified()); - Assert.False(editContext.IsModified(field1)); - Assert.False(editContext.IsModified(field2)); - } - - [Fact] - public void RaisesEventWhenFieldIsChanged() - { - // Arrange - var editContext = new EditContext(new object()); - var field1 = new FieldIdentifier(new object(), "fieldname"); // Shows it can be on a different model - var didReceiveNotification = false; - editContext.OnFieldChanged += (sender, eventArgs) => - { - Assert.Same(editContext, sender); - Assert.Equal(field1, eventArgs.FieldIdentifier); - didReceiveNotification = true; - }; - - // Act - editContext.NotifyFieldChanged(field1); - - // Assert - Assert.True(didReceiveNotification); - } - - [Fact] - public void CanEnumerateValidationMessagesAcrossAllStoresForSingleField() - { - // Arrange - var editContext = new EditContext(new object()); - var store1 = new ValidationMessageStore(editContext); - var store2 = new ValidationMessageStore(editContext); - var field = new FieldIdentifier(new object(), "field"); - var fieldWithNoState = new FieldIdentifier(new object(), "field with no state"); - store1.Add(field, "Store 1 message 1"); - store1.Add(field, "Store 1 message 2"); - store1.Add(new FieldIdentifier(new object(), "otherfield"), "Message for other field that should not appear in results"); - store2.Add(field, "Store 2 message 1"); - - // Act/Assert: Can pick out the messages for a field - Assert.Equal(new[] - { - "Store 1 message 1", - "Store 1 message 2", - "Store 2 message 1", - }, editContext.GetValidationMessages(field).OrderBy(x => x)); // Sort because the order isn't defined - - // Act/Assert: It's fine to ask for messages for a field with no associated state - Assert.Empty(editContext.GetValidationMessages(fieldWithNoState)); - - // Act/Assert: After clearing a single store, we only see the results from other stores - store1.Clear(field); - Assert.Equal(new[] { "Store 2 message 1", }, editContext.GetValidationMessages(field)); - } - - [Fact] - public void CanEnumerateValidationMessagesAcrossAllStoresForAllFields() - { - // Arrange - var editContext = new EditContext(new object()); - var store1 = new ValidationMessageStore(editContext); - var store2 = new ValidationMessageStore(editContext); - var field1 = new FieldIdentifier(new object(), "field1"); - var field2 = new FieldIdentifier(new object(), "field2"); - store1.Add(field1, "Store 1 field 1 message 1"); - store1.Add(field1, "Store 1 field 1 message 2"); - store1.Add(field2, "Store 1 field 2 message 1"); - store2.Add(field1, "Store 2 field 1 message 1"); - - // Act/Assert - Assert.Equal(new[] - { - "Store 1 field 1 message 1", - "Store 1 field 1 message 2", - "Store 1 field 2 message 1", - "Store 2 field 1 message 1", - }, editContext.GetValidationMessages().OrderBy(x => x)); // Sort because the order isn't defined - - // Act/Assert: After clearing a single store, we only see the results from other stores - store1.Clear(); - Assert.Equal(new[] { "Store 2 field 1 message 1", }, editContext.GetValidationMessages()); - } - - [Fact] - public void IsValidWithNoValidationMessages() - { - // Arrange - var editContext = new EditContext(new object()); - - // Act - var isValid = editContext.Validate(); - - // assert - Assert.True(isValid); - } - - [Fact] - public void IsInvalidWithValidationMessages() - { - // Arrange - var editContext = new EditContext(new object()); - var messages = new ValidationMessageStore(editContext); - messages.Add( - new FieldIdentifier(new object(), "some field"), - "Some message"); - - // Act - var isValid = editContext.Validate(); - - // assert - Assert.False(isValid); - } - - [Fact] - public void RequestsValidationWhenValidateIsCalled() - { - // Arrange - var editContext = new EditContext(new object()); - var messages = new ValidationMessageStore(editContext); - editContext.OnValidationRequested += (sender, eventArgs) => - { - Assert.Same(editContext, sender); - Assert.NotNull(eventArgs); - messages.Add( - new FieldIdentifier(new object(), "some field"), - "Some message"); - }; - - // Act - var isValid = editContext.Validate(); - - // assert - Assert.False(isValid); - Assert.Equal(new[] { "Some message" }, editContext.GetValidationMessages()); - } - } -} diff --git a/src/Components/Forms/test/FieldIdentifierTest.cs b/src/Components/Forms/test/FieldIdentifierTest.cs deleted file mode 100644 index f19751a45d28..000000000000 --- a/src/Components/Forms/test/FieldIdentifierTest.cs +++ /dev/null @@ -1,198 +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.Linq.Expressions; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Forms -{ - public class FieldIdentifierTest - { - [Fact] - public void CannotUseNullModel() - { - var ex = Assert.Throws(() => new FieldIdentifier(null, "somefield")); - Assert.Equal("model", ex.ParamName); - } - - [Fact] - public void CannotUseValueTypeModel() - { - var ex = Assert.Throws(() => new FieldIdentifier(DateTime.Now, "somefield")); - Assert.Equal("model", ex.ParamName); - Assert.StartsWith("The model must be a reference-typed object.", ex.Message); - } - - [Fact] - public void CannotUseNullFieldName() - { - var ex = Assert.Throws(() => new FieldIdentifier(new object(), null)); - Assert.Equal("fieldName", ex.ParamName); - } - - [Fact] - public void CanUseEmptyFieldName() - { - var fieldIdentifier = new FieldIdentifier(new object(), string.Empty); - Assert.Equal(string.Empty, fieldIdentifier.FieldName); - } - - [Fact] - public void CanGetModelAndFieldName() - { - // Arrange/Act - var model = new object(); - var fieldIdentifier = new FieldIdentifier(model, "someField"); - - // Assert - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal("someField", fieldIdentifier.FieldName); - } - - [Fact] - public void DistinctModelsProduceDistinctHashCodesAndNonEquality() - { - // Arrange - var fieldIdentifier1 = new FieldIdentifier(new object(), "field"); - var fieldIdentifier2 = new FieldIdentifier(new object(), "field"); - - // Act/Assert - Assert.NotEqual(fieldIdentifier1.GetHashCode(), fieldIdentifier2.GetHashCode()); - Assert.False(fieldIdentifier1.Equals(fieldIdentifier2)); - } - - [Fact] - public void DistinctFieldNamesProduceDistinctHashCodesAndNonEquality() - { - // Arrange - var model = new object(); - var fieldIdentifier1 = new FieldIdentifier(model, "field1"); - var fieldIdentifier2 = new FieldIdentifier(model, "field2"); - - // Act/Assert - Assert.NotEqual(fieldIdentifier1.GetHashCode(), fieldIdentifier2.GetHashCode()); - Assert.False(fieldIdentifier1.Equals(fieldIdentifier2)); - } - - [Fact] - public void SameContentsProduceSameHashCodesAndEquality() - { - // Arrange - var model = new object(); - var fieldIdentifier1 = new FieldIdentifier(model, "field"); - var fieldIdentifier2 = new FieldIdentifier(model, "field"); - - // Act/Assert - Assert.Equal(fieldIdentifier1.GetHashCode(), fieldIdentifier2.GetHashCode()); - Assert.True(fieldIdentifier1.Equals(fieldIdentifier2)); - } - - [Fact] - public void FieldNamesAreCaseSensitive() - { - // Arrange - var model = new object(); - var fieldIdentifierLower = new FieldIdentifier(model, "field"); - var fieldIdentifierPascal = new FieldIdentifier(model, "Field"); - - // Act/Assert - Assert.Equal("field", fieldIdentifierLower.FieldName); - Assert.Equal("Field", fieldIdentifierPascal.FieldName); - Assert.NotEqual(fieldIdentifierLower.GetHashCode(), fieldIdentifierPascal.GetHashCode()); - Assert.False(fieldIdentifierLower.Equals(fieldIdentifierPascal)); - } - - [Fact] - public void CanCreateFromExpression_Property() - { - var model = new TestModel(); - var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal(nameof(model.StringProperty), fieldIdentifier.FieldName); - } - - [Fact] - public void CannotCreateFromExpression_NonMember() - { - var ex = Assert.Throws(() => - FieldIdentifier.Create(() => new TestModel())); - Assert.Equal($"The provided expression contains a NewExpression which is not supported. {nameof(FieldIdentifier)} only supports simple member accessors (fields, properties) of an object.", ex.Message); - } - - [Fact] - public void CanCreateFromExpression_Field() - { - var model = new TestModel(); - var fieldIdentifier = FieldIdentifier.Create(() => model.StringField); - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal(nameof(model.StringField), fieldIdentifier.FieldName); - } - - [Fact] - public void CanCreateFromExpression_WithCastToObject() - { - // This case is needed because, if a component is declared as receiving - // an Expression>, then any value types will be implicitly cast - var model = new TestModel(); - Expression> accessor = () => model.IntProperty; - var fieldIdentifier = FieldIdentifier.Create(accessor); - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal(nameof(model.IntProperty), fieldIdentifier.FieldName); - } - - [Fact] - public void CanCreateFromExpression_MemberOfConstantExpression() - { - var fieldIdentifier = FieldIdentifier.Create(() => StringPropertyOnThisClass); - Assert.Same(this, fieldIdentifier.Model); - Assert.Equal(nameof(StringPropertyOnThisClass), fieldIdentifier.FieldName); - } - - [Fact] - public void CanCreateFromExpression_MemberOfChildObject() - { - var parentModel = new ParentModel { Child = new TestModel() }; - var fieldIdentifier = FieldIdentifier.Create(() => parentModel.Child.StringField); - Assert.Same(parentModel.Child, fieldIdentifier.Model); - Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); - } - - [Fact] - public void CanCreateFromExpression_MemberOfIndexedCollectionEntry() - { - var models = new List() { null, new TestModel() }; - var fieldIdentifier = FieldIdentifier.Create(() => models[1].StringField); - Assert.Same(models[1], fieldIdentifier.Model); - Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); - } - - [Fact] - public void CanCreateFromExpression_MemberOfObjectWithCast() - { - var model = new TestModel(); - var fieldIdentifier = FieldIdentifier.Create(() => ((TestModel)(object)model).StringField); - Assert.Same(model, fieldIdentifier.Model); - Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); - } - - string StringPropertyOnThisClass { get; set; } - - class TestModel - { - public string StringProperty { get; set; } - - public int IntProperty { get; set; } - -#pragma warning disable 649 - public string StringField; -#pragma warning restore 649 - } - - class ParentModel - { - public TestModel Child { get; set; } - } - } -} diff --git a/src/Components/Forms/test/Microsoft.AspNetCore.Components.Forms.Tests.csproj b/src/Components/Forms/test/Microsoft.AspNetCore.Components.Forms.Tests.csproj deleted file mode 100644 index 6c611379a5ca..000000000000 --- a/src/Components/Forms/test/Microsoft.AspNetCore.Components.Forms.Tests.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - $(DefaultNetCoreTargetFramework) - Microsoft.AspNetCore.Components.Forms - - - - - - - - - - - - diff --git a/src/Components/Forms/test/ValidationMessageStoreTest.cs b/src/Components/Forms/test/ValidationMessageStoreTest.cs deleted file mode 100644 index 5264e254bd4b..000000000000 --- a/src/Components/Forms/test/ValidationMessageStoreTest.cs +++ /dev/null @@ -1,96 +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 Xunit; - -namespace Microsoft.AspNetCore.Components.Forms -{ - public class ValidationMessageStoreTest - { - [Fact] - public void CannotUseNullEditContext() - { - var ex = Assert.Throws(() => new ValidationMessageStore(null)); - Assert.Equal("editContext", ex.ParamName); - } - - [Fact] - public void CanCreateForEditContext() - { - new ValidationMessageStore(new EditContext(new object())); - } - - [Fact] - public void CanAddMessages() - { - // Arrange - var messages = new ValidationMessageStore(new EditContext(new object())); - var field1 = new FieldIdentifier(new object(), "field1"); - var field2 = new FieldIdentifier(new object(), "field2"); - var field3 = new FieldIdentifier(new object(), "field3"); - - // Act - messages.Add(field1, "Field 1 message 1"); - messages.Add(field1, "Field 1 message 2"); - messages.Add(field2, "Field 2 message 1"); - - // Assert - Assert.Equal(new[] { "Field 1 message 1", "Field 1 message 2" }, messages[field1]); - Assert.Equal(new[] { "Field 2 message 1" }, messages[field2]); - Assert.Empty(messages[field3]); - } - - [Fact] - public void CanAddMessagesMultiple() - { - // Arrange - var messages = new ValidationMessageStore(new EditContext(new object())); - var field1 = new FieldIdentifier(new object(), "field1"); - var entries = new[] { "A", "B", "C" }; - - // Act - messages.Add(field1, entries); - - // Assert - Assert.Equal(entries, messages[field1]); - } - - [Fact] - public void CanClearMessagesForSingleField() - { - // Arrange - var messages = new ValidationMessageStore(new EditContext(new object())); - var field1 = new FieldIdentifier(new object(), "field1"); - var field2 = new FieldIdentifier(new object(), "field2"); - messages.Add(field1, "Field 1 message 1"); - messages.Add(field1, "Field 1 message 2"); - messages.Add(field2, "Field 2 message 1"); - - // Act - messages.Clear(field1); - - // Assert - Assert.Empty(messages[field1]); - Assert.Equal(new[] { "Field 2 message 1" }, messages[field2]); - } - - [Fact] - public void CanClearMessagesForAllFields() - { - // Arrange - var messages = new ValidationMessageStore(new EditContext(new object())); - var field1 = new FieldIdentifier(new object(), "field1"); - var field2 = new FieldIdentifier(new object(), "field2"); - messages.Add(field1, "Field 1 message 1"); - messages.Add(field2, "Field 2 message 1"); - - // Act - messages.Clear(); - - // Assert - Assert.Empty(messages[field1]); - Assert.Empty(messages[field2]); - } - } -} diff --git a/src/Components/Ignitor/src/BlazorClient.cs b/src/Components/Ignitor/src/BlazorClient.cs deleted file mode 100644 index 46637eb3bbe6..000000000000 --- a/src/Components/Ignitor/src/BlazorClient.cs +++ /dev/null @@ -1,540 +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.Net.Http; -using System.Text.Json; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.SignalR.Client; -using Microsoft.AspNetCore.SignalR.Protocol; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -#nullable enable -namespace Ignitor -{ - public class BlazorClient : IAsyncDisposable - { - private const string MarkerPattern = ".*?.*?"; - private HubConnection? _hubConnection; - - public BlazorClient() - { - CancellationTokenSource = new CancellationTokenSource(); - CancellationToken = CancellationTokenSource.Token; - TaskCompletionSource = new TaskCompletionSource(); - - CancellationTokenSource.Token.Register(() => - { - TaskCompletionSource.TrySetCanceled(); - }); - } - - public TimeSpan? DefaultConnectionTimeout { get; set; } = TimeSpan.FromSeconds(20); - public TimeSpan? DefaultOperationTimeout { get; set; } = TimeSpan.FromMilliseconds(500); - - /// - /// Gets or sets a value that determines whether the client will capture data such - /// as render batches, interop calls, and errors for later inspection. - /// - public bool CaptureOperations { get; set; } - - /// - /// Gets the collections of operation results that are captured when - /// is true. - /// - public Operations Operations { get; } = new Operations(); - - public Func? FormatError { get; set; } - - private CancellationTokenSource CancellationTokenSource { get; } - - private CancellationToken CancellationToken { get; } - - private TaskCompletionSource TaskCompletionSource { get; } - - private CancellableOperation? NextAttachComponentReceived { get; set; } - - private CancellableOperation? NextBatchReceived { get; set; } - - private CancellableOperation? NextErrorReceived { get; set; } - - private CancellableOperation? NextDisconnect { get; set; } - - private CancellableOperation? NextJSInteropReceived { get; set; } - - private CancellableOperation? NextDotNetInteropCompletionReceived { get; set; } - - public ILoggerProvider LoggerProvider { get; set; } = NullLoggerProvider.Instance; - - public bool ConfirmRenderBatch { get; set; } = true; - - public event Action? JSInterop; - - public event Action? RenderBatchReceived; - - public event Action? DotNetInteropCompletion; - - public event Action? OnCircuitError; - - public string? CircuitId { get; private set; } - - public ElementHive Hive { get; } = new ElementHive(); - - public bool ImplicitWait => DefaultOperationTimeout != null; - - public HubConnection HubConnection => _hubConnection ?? throw new InvalidOperationException("HubConnection has not been initialized."); - - public Task PrepareForNextBatch(TimeSpan? timeout) - { - if (NextBatchReceived != null && !NextBatchReceived.Disposed) - { - throw new InvalidOperationException("Invalid state previous task not completed"); - } - - NextBatchReceived = new CancellableOperation(timeout, CancellationToken); - return NextBatchReceived.Completion.Task; - } - - public Task PrepareForNextJSInterop(TimeSpan? timeout) - { - if (NextJSInteropReceived != null && !NextJSInteropReceived.Disposed) - { - throw new InvalidOperationException("Invalid state previous task not completed"); - } - - NextJSInteropReceived = new CancellableOperation(timeout, CancellationToken); - - return NextJSInteropReceived.Completion.Task; - } - - public Task PrepareForNextDotNetInterop(TimeSpan? timeout) - { - if (NextDotNetInteropCompletionReceived != null && !NextDotNetInteropCompletionReceived.Disposed) - { - throw new InvalidOperationException("Invalid state previous task not completed"); - } - - NextDotNetInteropCompletionReceived = new CancellableOperation(timeout, CancellationToken); - - return NextDotNetInteropCompletionReceived.Completion.Task; - } - - public Task PrepareForNextCircuitError(TimeSpan? timeout) - { - if (NextErrorReceived != null && !NextErrorReceived.Disposed) - { - throw new InvalidOperationException("Invalid state previous task not completed"); - } - - NextErrorReceived = new CancellableOperation(timeout, CancellationToken); - - return NextErrorReceived.Completion.Task; - } - - public Task PrepareForNextDisconnect(TimeSpan? timeout) - { - if (NextDisconnect != null && !NextDisconnect.Disposed) - { - throw new InvalidOperationException("Invalid state previous task not completed"); - } - - NextDisconnect = new CancellableOperation(timeout, CancellationToken); - - return NextDisconnect.Completion.Task; - } - - public Task ClickAsync(string elementId, bool expectRenderBatch = true) - { - if (!Hive.TryFindElementById(elementId, out var elementNode)) - { - throw new InvalidOperationException($"Could not find element with id {elementId}."); - } - if (expectRenderBatch) - { - return ExpectRenderBatch(() => elementNode.ClickAsync(HubConnection)); - } - else - { - return elementNode.ClickAsync(HubConnection); - } - } - - public Task SelectAsync(string elementId, string value) - { - if (!Hive.TryFindElementById(elementId, out var elementNode)) - { - throw new InvalidOperationException($"Could not find element with id {elementId}."); - } - - return ExpectRenderBatch(() => elementNode.SelectAsync(HubConnection, value)); - } - - public async Task ExpectRenderBatch(Func action, TimeSpan? timeout = null) - { - var task = WaitForRenderBatch(timeout); - await action(); - return await task; - } - - public async Task ExpectJSInterop(Func action, TimeSpan? timeout = null) - { - var task = WaitForJSInterop(timeout); - await action(); - return await task; - } - - public async Task ExpectDotNetInterop(Func action, TimeSpan? timeout = null) - { - var task = WaitForDotNetInterop(timeout); - await action(); - return await task; - } - - public async Task ExpectCircuitError(Func action, TimeSpan? timeout = null) - { - var task = WaitForCircuitError(timeout); - await action(); - return await task; - } - - public async Task ExpectDisconnect(Func action, TimeSpan? timeout = null) - { - var task = WaitForDisconnect(timeout); - await action(); - return await task; - } - - public async Task<(string? error, Exception? exception)> ExpectCircuitErrorAndDisconnect(Func action, TimeSpan? timeout = null) - { - string? error = default; - - // NOTE: timeout is used for each operation individually. - var exception = await ExpectDisconnect(async () => - { - error = await ExpectCircuitError(action, timeout); - }, timeout); - - return (error, exception); - } - - private async Task WaitForRenderBatch(TimeSpan? timeout = null) - { - if (ImplicitWait) - { - if (DefaultOperationTimeout == null && timeout == null) - { - throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed."); - } - - try - { - return await PrepareForNextBatch(timeout ?? DefaultOperationTimeout); - } - catch (TimeoutException) when (FormatError != null) - { - throw FormatError("Timed out while waiting for batch."); - } - } - - return null; - } - - private async Task WaitForJSInterop(TimeSpan? timeout = null) - { - if (ImplicitWait) - { - if (DefaultOperationTimeout == null && timeout == null) - { - throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed."); - } - - try - { - return await PrepareForNextJSInterop(timeout ?? DefaultOperationTimeout); - } - catch (TimeoutException) when (FormatError != null) - { - throw FormatError("Timed out while waiting for JS Interop."); - } - } - - return null; - } - - private async Task WaitForDotNetInterop(TimeSpan? timeout = null) - { - if (ImplicitWait) - { - if (DefaultOperationTimeout == null && timeout == null) - { - throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed."); - } - - try - { - return await PrepareForNextDotNetInterop(timeout ?? DefaultOperationTimeout); - } - catch (TimeoutException) when (FormatError != null) - { - throw FormatError("Timed out while waiting for .NET interop."); - } - } - - return null; - } - - private async Task WaitForCircuitError(TimeSpan? timeout = null) - { - if (ImplicitWait) - { - if (DefaultOperationTimeout == null && timeout == null) - { - throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed."); - } - - try - { - return await PrepareForNextCircuitError(timeout ?? DefaultOperationTimeout); - } - catch (TimeoutException) when (FormatError != null) - { - throw FormatError("Timed out while waiting for circuit error."); - } - } - - return null; - } - - private async Task WaitForDisconnect(TimeSpan? timeout = null) - { - if (ImplicitWait) - { - if (DefaultOperationTimeout == null && timeout == null) - { - throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed."); - } - - try - { - return await PrepareForNextDisconnect(timeout ?? DefaultOperationTimeout); - } - catch (TimeoutException) when (FormatError != null) - { - throw FormatError("Timed out while waiting for disconnect."); - } - } - - return null; - } - - public async Task ConnectAsync(Uri uri, bool connectAutomatically = true) - { - var builder = new HubConnectionBuilder(); - builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); - builder.WithUrl(GetHubUrl(uri)); - builder.ConfigureLogging(l => - { - l.SetMinimumLevel(LogLevel.Trace); - if (LoggerProvider != null) - { - l.AddProvider(LoggerProvider); - } - }); - - _hubConnection = builder.Build(); - - HubConnection.On("JS.AttachComponent", OnAttachComponent); - HubConnection.On("JS.BeginInvokeJS", OnBeginInvokeJS); - HubConnection.On("JS.EndInvokeDotNet", OnEndInvokeDotNet); - HubConnection.On("JS.RenderBatch", OnRenderBatch); - HubConnection.On("JS.Error", OnError); - HubConnection.Closed += OnClosedAsync; - - await HubConnection.StartAsync(CancellationToken); - - if (!connectAutomatically) - { - return true; - } - - var descriptors = await GetPrerenderDescriptors(uri); - await ExpectRenderBatch( - async () => CircuitId = await HubConnection.InvokeAsync("StartCircuit", uri, uri, descriptors, CancellationToken), - DefaultConnectionTimeout); - return CircuitId != null; - } - - private void OnEndInvokeDotNet(string message) - { - Operations?.DotNetCompletions.Enqueue(message); - DotNetInteropCompletion?.Invoke(message); - - NextDotNetInteropCompletionReceived?.Completion?.TrySetResult(null); - } - - private void OnAttachComponent(int componentId, string domSelector) - { - var call = new CapturedAttachComponentCall(componentId, domSelector); - Operations?.AttachComponent.Enqueue(call); - - NextAttachComponentReceived?.Completion?.TrySetResult(call); - } - - private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson) - { - var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson); - Operations?.JSInteropCalls.Enqueue(call); - JSInterop?.Invoke(call); - - NextJSInteropReceived?.Completion?.TrySetResult(null); - } - - private void OnRenderBatch(int id, byte[] data) - { - var capturedBatch = new CapturedRenderBatch(id, data); - - Operations?.Batches.Enqueue(capturedBatch); - RenderBatchReceived?.Invoke(capturedBatch); - - var batch = RenderBatchReader.Read(data); - - Hive.Update(batch); - - if (ConfirmRenderBatch) - { - _ = ConfirmBatch(id); - } - - NextBatchReceived?.Completion?.TrySetResult(null); - } - - public Task ConfirmBatch(int batchId, string? error = null) - { - return HubConnection.InvokeAsync("OnRenderCompleted", batchId, error, CancellationToken); - } - - private void OnError(string error) - { - Operations?.Errors.Enqueue(error); - OnCircuitError?.Invoke(error); - - // If we get an error, forcibly terminate anything else we're waiting for. These - // tests should only encounter errors in specific situations, and this ensures that - // we fail with a good message. - var exception = FormatError?.Invoke(error) ?? new Exception(error); - NextBatchReceived?.Completion?.TrySetException(exception); - NextDotNetInteropCompletionReceived?.Completion.TrySetException(exception); - NextJSInteropReceived?.Completion.TrySetException(exception); - NextAttachComponentReceived?.Completion?.TrySetException(exception); - NextErrorReceived?.Completion?.TrySetResult(null); - } - - private Task OnClosedAsync(Exception ex) - { - NextDisconnect?.Completion?.TrySetResult(null); - - if (ex == null) - { - TaskCompletionSource.TrySetResult(null); - } - else - { - TaskCompletionSource.TrySetException(ex); - } - - return Task.CompletedTask; - } - - private Uri GetHubUrl(Uri uri) - { - if (uri.Segments.Length == 1) - { - return new Uri(uri, "_blazor"); - } - else - { - var builder = new UriBuilder(uri); - builder.Path += builder.Path.EndsWith("/") ? "_blazor" : "/_blazor"; - return builder.Uri; - } - } - - public async Task InvokeDotNetMethod(object callId, string assemblyName, string methodIdentifier, object dotNetObjectId, string argsJson) - { - await ExpectDotNetInterop(() => HubConnection.InvokeAsync( - "BeginInvokeDotNetFromJS", - callId?.ToString(), - assemblyName, - methodIdentifier, - dotNetObjectId ?? 0, - argsJson, - CancellationToken)); - } - - public async Task GetPrerenderDescriptors(Uri uri) - { - var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Cookie", "__blazor_execution_mode=server"); - var response = await httpClient.GetAsync(uri); - response.EnsureSuccessStatusCode(); - var content = await response.Content.ReadAsStringAsync(); - - var match = ReadMarkers(content); - return $"[{string.Join(", ", match)}]"; - } - - public void Cancel() - { - if (!CancellationTokenSource.IsCancellationRequested) - { - CancellationTokenSource.Cancel(); - CancellationTokenSource.Dispose(); - } - } - - public ElementNode FindElementById(string id) - { - if (!Hive.TryFindElementById(id, out var element)) - { - throw new InvalidOperationException($"Element with id '{id}' was not found."); - } - - return element; - } - - private string[] ReadMarkers(string content) - { - content = content.Replace("\r\n", "").Replace("\n", ""); - var matches = Regex.Matches(content, MarkerPattern); - var markers = matches.Select(s => (value: s.Groups[1].Value, parsed: JsonDocument.Parse(s.Groups[1].Value))) - .Where(s => - { - return s.parsed.RootElement.TryGetProperty("type", out var markerType) && - markerType.ValueKind != JsonValueKind.Undefined && - markerType.GetString() == "server"; - }) - .OrderBy(p => p.parsed.RootElement.GetProperty("sequence").GetInt32()) - .Select(p => p.value) - .ToArray(); - - return markers; - } - - public async ValueTask DisposeAsync() - { - Cancel(); - if (HubConnection != null) - { - await HubConnection.DisposeAsync(); - } - } - } -} - -#nullable restore diff --git a/src/Components/Ignitor/src/CancellableOperation.cs b/src/Components/Ignitor/src/CancellableOperation.cs deleted file mode 100644 index 6e1f217d19fa..000000000000 --- a/src/Components/Ignitor/src/CancellableOperation.cs +++ /dev/null @@ -1,78 +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.Threading; -using System.Threading.Tasks; - -#nullable enable -namespace Ignitor -{ - internal class CancellableOperation - { - public CancellableOperation(TimeSpan? timeout, CancellationToken cancellationToken) - { - Timeout = timeout; - - Completion = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); - Completion.Task.ContinueWith( - (task, state) => - { - var operation = (CancellableOperation)state!; - operation.Dispose(); - }, - this, - TaskContinuationOptions.ExecuteSynchronously); // We need to execute synchronously to clean-up before anything else continues - - - Cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - - if (Timeout != null && Timeout != System.Threading.Timeout.InfiniteTimeSpan && Timeout != TimeSpan.MaxValue) - { - Cancellation.CancelAfter(Timeout.Value); - } - - CancellationRegistration = Cancellation.Token.Register( - (self) => - { - var operation = (CancellableOperation)self!; - - if (cancellationToken.IsCancellationRequested) - { - // The operation was externally canceled before it timed out. - Dispose(); - return; - } - - operation.Completion.TrySetException(new TimeoutException($"The operation timed out after {Timeout}.")); - operation.Cancellation?.Dispose(); - operation.CancellationRegistration.Dispose(); - }, - this); - } - - public TimeSpan? Timeout { get; } - - public TaskCompletionSource Completion { get; } - - public CancellationTokenSource Cancellation { get; } - - public CancellationTokenRegistration CancellationRegistration { get; } - - public bool Disposed { get; private set; } - - private void Dispose() - { - if (Disposed) - { - return; - } - - Disposed = true; - Completion.TrySetCanceled(Cancellation.Token); - Cancellation.Dispose(); - CancellationRegistration.Dispose(); - } - } -} -#nullable restore diff --git a/src/Components/Ignitor/src/CapturedAttachComponentCall.cs b/src/Components/Ignitor/src/CapturedAttachComponentCall.cs deleted file mode 100644 index b3897c95792c..000000000000 --- a/src/Components/Ignitor/src/CapturedAttachComponentCall.cs +++ /dev/null @@ -1,17 +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 Ignitor -{ - public readonly struct CapturedAttachComponentCall - { - public CapturedAttachComponentCall(int componentId, string selector) - { - ComponentId = componentId; - Selector = selector; - } - - public int ComponentId { get; } - public string Selector { get; } - } -} diff --git a/src/Components/Ignitor/src/CapturedJSInteropCall.cs b/src/Components/Ignitor/src/CapturedJSInteropCall.cs deleted file mode 100644 index 4af491a58abd..000000000000 --- a/src/Components/Ignitor/src/CapturedJSInteropCall.cs +++ /dev/null @@ -1,19 +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 Ignitor -{ - public class CapturedJSInteropCall - { - public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson) - { - AsyncHandle = asyncHandle; - Identifier = identifier; - ArgsJson = argsJson; - } - - public int AsyncHandle { get; } - public string Identifier { get; } - public string ArgsJson { get; } - } -} diff --git a/src/Components/Ignitor/src/CapturedRenderBatch.cs b/src/Components/Ignitor/src/CapturedRenderBatch.cs deleted file mode 100644 index df2de87e9fc7..000000000000 --- a/src/Components/Ignitor/src/CapturedRenderBatch.cs +++ /dev/null @@ -1,17 +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 Ignitor -{ - public class CapturedRenderBatch - { - public CapturedRenderBatch(int id, byte[] data) - { - Id = id; - Data = data; - } - - public int Id { get; } - public byte[] Data { get; } - } -} diff --git a/src/Components/Ignitor/src/CommentNode.cs b/src/Components/Ignitor/src/CommentNode.cs deleted file mode 100644 index 9f273e5d61e5..000000000000 --- a/src/Components/Ignitor/src/CommentNode.cs +++ /dev/null @@ -1,9 +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 Ignitor -{ - internal class LogicalContainerNode : ContainerNode - { - } -} diff --git a/src/Components/Ignitor/src/ComponentNode.cs b/src/Components/Ignitor/src/ComponentNode.cs deleted file mode 100644 index a6829bb3072c..000000000000 --- a/src/Components/Ignitor/src/ComponentNode.cs +++ /dev/null @@ -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 Ignitor -{ - public class ComponentNode : ContainerNode - { - private readonly int _componentId; - - public ComponentNode(int componentId) - { - _componentId = componentId; - } - } -} diff --git a/src/Components/Ignitor/src/ComponentState.cs b/src/Components/Ignitor/src/ComponentState.cs deleted file mode 100644 index 28683bee116e..000000000000 --- a/src/Components/Ignitor/src/ComponentState.cs +++ /dev/null @@ -1,18 +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 Ignitor -{ -#nullable enable - public class ComponentState - { - public ComponentState(int componentId) - { - ComponentId = componentId; - } - - public int ComponentId { get; } - public IComponent? Component { get; } - } -#nullable restore -} diff --git a/src/Components/Ignitor/src/ContainerNode.cs b/src/Components/Ignitor/src/ContainerNode.cs deleted file mode 100644 index 24ee50b45895..000000000000 --- a/src/Components/Ignitor/src/ContainerNode.cs +++ /dev/null @@ -1,86 +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; - -#nullable enable -namespace Ignitor -{ - public abstract class ContainerNode : Node - { - private readonly List _children; - - protected ContainerNode() - { - _children = new List(); - } - - public IReadOnlyList Children => _children; - - public void InsertLogicalChild(Node child, int childIndex) - { - if (child is LogicalContainerNode comment && comment.Children.Count > 0) - { - // There's nothing to stop us implementing support for this scenario, and it's not difficult - // (after inserting 'child' itself, also iterate through its logical children and physically - // put them as following-siblings in the DOM). However there's no scenario that requires it - // presently, so if we did implement it there'd be no good way to have tests for it. - throw new Exception("Not implemented: inserting non-empty logical container"); - } - - if (child.Parent != null) - { - // Likewise, we could easily support this scenario too (in this 'if' block, just splice - // out 'child' from the logical children array of its previous logical parent by using - // Array.prototype.indexOf to determine its previous sibling index). - // But again, since there's not currently any scenario that would use it, we would not - // have any test coverage for such an implementation. - throw new NotSupportedException("Not implemented: moving existing logical children"); - } - - if (childIndex < Children.Count) - { - // Insert - _children.Insert(childIndex, child); - } - else - { - // Append - _children.Add(child); - } - - child.Parent = this; - } - - public ContainerNode CreateAndInsertContainer(int childIndex) - { - var containerElement = new LogicalContainerNode(); - InsertLogicalChild(containerElement, childIndex); - return containerElement; - } - - public ComponentNode CreateAndInsertComponent(int componentId, int childIndex) - { - var componentElement = new ComponentNode(componentId); - InsertLogicalChild(componentElement, childIndex); - return componentElement; - } - - public void RemoveLogicalChild(int childIndex) - { - var childToRemove = Children[childIndex]; - _children.RemoveAt(childIndex); - - // If it's a logical container, also remove its descendants - if (childToRemove is LogicalContainerNode container) - { - while (container.Children.Count > 0) - { - container.RemoveLogicalChild(0); - } - } - } - } -} -#nullable restore diff --git a/src/Components/Ignitor/src/ElementHive.cs b/src/Components/Ignitor/src/ElementHive.cs deleted file mode 100644 index 3bb37c38ce1b..000000000000 --- a/src/Components/Ignitor/src/ElementHive.cs +++ /dev/null @@ -1,475 +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.CodeAnalysis; - -#nullable enable -namespace Ignitor -{ - public class ElementHive - { - private const string SelectValuePropname = "_blazorSelectValue"; - - public Dictionary Components { get; } = new Dictionary(); - - public string SerializedValue => NodeSerializer.Serialize(this); - - public void Update(RenderBatch batch) - { - for (var i = 0; i < batch.UpdatedComponents.Count; i++) - { - var diff = batch.UpdatedComponents.Array[i]; - var componentId = diff.ComponentId; - var edits = diff.Edits; - UpdateComponent(batch, componentId, edits); - } - - for (var i = 0; i < batch.DisposedComponentIDs.Count; i++) - { - DisposeComponent(batch.DisposedComponentIDs.Array[i]); - } - - for (var i = 0; i < batch.DisposedEventHandlerIDs.Count; i++) - { - DisposeEventHandler(batch.DisposedEventHandlerIDs.Array[i]); - } - } - - public bool TryFindElementById(string id, [NotNullWhen(true)] out ElementNode? element) - { - foreach (var kvp in Components) - { - var component = kvp.Value; - if (TryGetElementFromChildren(component, out element)) - { - return true; - } - } - - element = null; - return false; - - bool TryGetElementFromChildren(Node node, out ElementNode? foundNode) - { - if (node is ElementNode elementNode && - elementNode.Attributes.TryGetValue("id", out var elementId) && - elementId?.ToString() == id) - { - foundNode = elementNode; - return true; - } - - if (node is ContainerNode containerNode) - { - for (var i = 0; i < containerNode.Children.Count; i++) - { - if (TryGetElementFromChildren(containerNode.Children[i], out foundNode)) - { - return true; - } - } - } - - foundNode = null; - return false; - } - } - - private void UpdateComponent(RenderBatch batch, int componentId, ArrayBuilderSegment edits) - { - if (!Components.TryGetValue(componentId, out var component)) - { - component = new ComponentNode(componentId); - Components.Add(componentId, component); - - } - - ApplyEdits(batch, component, 0, edits); - } - - private void DisposeComponent(int componentId) - { - - } - - private void DisposeEventHandler(ulong eventHandlerId) - { - - } - - private void ApplyEdits(RenderBatch batch, ContainerNode parent, int childIndex, ArrayBuilderSegment edits) - { - var currentDepth = 0; - var childIndexAtCurrentDepth = childIndex; - var permutations = new List(); - - for (var editIndex = edits.Offset; editIndex < edits.Offset + edits.Count; editIndex++) - { - var edit = edits.Array[editIndex]; - switch (edit.Type) - { - case RenderTreeEditType.PrependFrame: - { - var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex]; - var siblingIndex = edit.SiblingIndex; - InsertFrame(batch, parent, childIndexAtCurrentDepth + siblingIndex, batch.ReferenceFrames.Array, frame, edit.ReferenceFrameIndex); - break; - } - - case RenderTreeEditType.RemoveFrame: - { - var siblingIndex = edit.SiblingIndex; - parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex); - break; - } - - case RenderTreeEditType.SetAttribute: - { - var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex]; - var siblingIndex = edit.SiblingIndex; - var node = parent.Children[childIndexAtCurrentDepth + siblingIndex]; - if (node is ElementNode element) - { - ApplyAttribute(batch, element, frame); - } - else - { - throw new Exception("Cannot set attribute on non-element child"); - } - break; - } - - case RenderTreeEditType.RemoveAttribute: - { - // Note that we don't have to dispose the info we track about event handlers here, because the - // disposed event handler IDs are delivered separately (in the 'disposedEventHandlerIds' array) - var siblingIndex = edit.SiblingIndex; - var node = parent.Children[childIndexAtCurrentDepth + siblingIndex]; - if (node is ElementNode element) - { - var attributeName = edit.RemovedAttributeName; - - // First try to remove any special property we use for this attribute - if (!TryApplySpecialProperty(batch, element, attributeName, default)) - { - // If that's not applicable, it's a regular DOM attribute so remove that - element.RemoveAttribute(attributeName); - } - } - else - { - throw new Exception("Cannot remove attribute from non-element child"); - } - break; - } - - case RenderTreeEditType.UpdateText: - { - var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex]; - var siblingIndex = edit.SiblingIndex; - var node = parent.Children[childIndexAtCurrentDepth + siblingIndex]; - if (node is TextNode textNode) - { - textNode.TextContent = frame.TextContent; - } - else - { - throw new Exception("Cannot set text content on non-text child"); - } - break; - } - - - case RenderTreeEditType.UpdateMarkup: - { - var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex]; - var siblingIndex = edit.SiblingIndex; - parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex); - InsertMarkup(parent, childIndexAtCurrentDepth + siblingIndex, frame); - break; - } - - case RenderTreeEditType.StepIn: - { - var siblingIndex = edit.SiblingIndex; - parent = (ContainerNode)parent.Children[childIndexAtCurrentDepth + siblingIndex]; - currentDepth++; - childIndexAtCurrentDepth = 0; - break; - } - - case RenderTreeEditType.StepOut: - { - parent = parent.Parent ?? throw new InvalidOperationException($"Cannot step out of {parent}"); - currentDepth--; - childIndexAtCurrentDepth = currentDepth == 0 ? childIndex : 0; // The childIndex is only ever nonzero at zero depth - break; - } - - case RenderTreeEditType.PermutationListEntry: - { - permutations.Add(new PermutationListEntry(childIndexAtCurrentDepth + edit.SiblingIndex, childIndexAtCurrentDepth + edit.MoveToSiblingIndex)); - break; - } - - case RenderTreeEditType.PermutationListEnd: - { - throw new NotSupportedException(); - //permuteLogicalChildren(parent, permutations!); - //permutations.Clear(); - //break; - } - - default: - { - throw new Exception($"Unknown edit type: '{edit.Type}'"); - } - } - } - } - - private int InsertFrame(RenderBatch batch, ContainerNode parent, int childIndex, ArraySegment frames, RenderTreeFrame frame, int frameIndex) - { - switch (frame.FrameType) - { - case RenderTreeFrameType.Element: - { - InsertElement(batch, parent, childIndex, frames, frame, frameIndex); - return 1; - } - - case RenderTreeFrameType.Text: - { - InsertText(parent, childIndex, frame); - return 1; - } - - case RenderTreeFrameType.Attribute: - { - throw new Exception("Attribute frames should only be present as leading children of element frames."); - } - - case RenderTreeFrameType.Component: - { - InsertComponent(parent, childIndex, frame); - return 1; - } - - case RenderTreeFrameType.Region: - { - return InsertFrameRange(batch, parent, childIndex, frames, frameIndex + 1, frameIndex + CountDescendantFrames(frame)); - } - - case RenderTreeFrameType.ElementReferenceCapture: - { - // No action for reference captures. - break; - } - - case RenderTreeFrameType.Markup: - { - InsertMarkup(parent, childIndex, frame); - return 1; - } - - } - - throw new Exception($"Unknown frame type: {frame.FrameType}"); - } - - private void InsertText(ContainerNode parent, int childIndex, RenderTreeFrame frame) - { - var textContent = frame.TextContent; - var newTextNode = new TextNode(textContent); - parent.InsertLogicalChild(newTextNode, childIndex); - } - - private void InsertComponent(ContainerNode parent, int childIndex, RenderTreeFrame frame) - { - // All we have to do is associate the child component ID with its location. We don't actually - // do any rendering here, because the diff for the child will appear later in the render batch. - var childComponentId = frame.ComponentId; - var containerElement = parent.CreateAndInsertComponent(childComponentId, childIndex); - - Components[childComponentId] = containerElement; - } - - private int InsertFrameRange(RenderBatch batch, ContainerNode parent, int childIndex, ArraySegment frames, int startIndex, int endIndexExcl) - { - var origChildIndex = childIndex; - for (var index = startIndex; index < endIndexExcl; index++) - { - var frame = batch.ReferenceFrames.Array[index]; - var numChildrenInserted = InsertFrame(batch, parent, childIndex, frames, frame, index); - childIndex += numChildrenInserted; - - // Skip over any descendants, since they are already dealt with recursively - index += CountDescendantFrames(frame); - } - - return (childIndex - origChildIndex); // Total number of children inserted - } - - private void InsertElement(RenderBatch batch, ContainerNode parent, int childIndex, ArraySegment frames, RenderTreeFrame frame, int frameIndex) - { - // Note: we don't handle SVG here - var newElement = new ElementNode(frame.ElementName); - parent.InsertLogicalChild(newElement, childIndex); - - // Apply attributes - for (var i = frameIndex + 1; i < frameIndex + frame.ElementSubtreeLength; i++) - { - var descendantFrame = batch.ReferenceFrames.Array[i]; - if (descendantFrame.FrameType == RenderTreeFrameType.Attribute) - { - ApplyAttribute(batch, newElement, descendantFrame); - } - else - { - // As soon as we see a non-attribute child, all the subsequent child frames are - // not attributes, so bail out and insert the remnants recursively - InsertFrameRange(batch, newElement, 0, frames, i, frameIndex + frame.ElementSubtreeLength); - break; - } - } - } - - private void ApplyAttribute(RenderBatch batch, ElementNode elementNode, RenderTreeFrame attributeFrame) - { - var attributeName = attributeFrame.AttributeName; - var eventHandlerId = attributeFrame.AttributeEventHandlerId; - - if (eventHandlerId != 0) - { - var firstTwoChars = attributeName.Substring(0, 2); - var eventName = attributeName.Substring(2); - if (firstTwoChars != "on" || string.IsNullOrEmpty(eventName)) - { - throw new InvalidOperationException($"Attribute has nonzero event handler ID, but attribute name '${attributeName}' does not start with 'on'."); - } - var descriptor = new ElementNode.ElementEventDescriptor(eventName, eventHandlerId); - elementNode.SetEvent(eventName, descriptor); - - return; - } - - // First see if we have special handling for this attribute - if (!TryApplySpecialProperty(batch, elementNode, attributeName, attributeFrame)) - { - // If not, treat it as a regular string-valued attribute - elementNode.SetAttribute( - attributeName, - attributeFrame.AttributeValue); - } - } - - private bool TryApplySpecialProperty(RenderBatch batch, ElementNode element, string attributeName, RenderTreeFrame attributeFrame) - { - switch (attributeName) - { - case "value": - return TryApplyValueProperty(element, attributeFrame); - case "checked": - return TryApplyCheckedProperty(element, attributeFrame); - default: - return false; - } - } - - - - private bool TryApplyValueProperty(ElementNode element, RenderTreeFrame attributeFrame) - { - // Certain elements have built-in behaviour for their 'value' property - switch (element.TagName) - { - case "INPUT": - case "SELECT": - case "TEXTAREA": - { - var value = attributeFrame.AttributeValue; - element.SetProperty("value", value); - - if (element.TagName == "SELECT") - { - // s in some browsers, due to the limited stylability of ``s in IE10+.\n &::-ms-expand {\n background-color: transparent;\n border: 0;\n }\n\n // Customize the `:focus` state to imitate native WebKit styles.\n @include form-control-focus();\n\n // Placeholder\n &::placeholder {\n color: $input-placeholder-color;\n // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.\n opacity: 1;\n }\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &:disabled,\n &[readonly] {\n background-color: $input-disabled-bg;\n // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.\n opacity: 1;\n }\n}\n\nselect.form-control {\n &:focus::-ms-value {\n // Suppress the nested default white text on blue background highlight given to\n // the selected option text when the (still closed) receives focus\n // in IE and (under certain conditions) Edge.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n }\n\n &[multiple],\n &[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: $custom-select-padding-x;\n background-image: none;\n }\n\n &:disabled {\n color: $custom-select-disabled-color;\n background-color: $custom-select-disabled-bg;\n }\n\n // Hides the default caret in IE11\n &::-ms-expand {\n display: none;\n }\n}\n\n.custom-select-sm {\n height: $custom-select-height-sm;\n padding-top: $custom-select-padding-y-sm;\n padding-bottom: $custom-select-padding-y-sm;\n padding-left: $custom-select-padding-x-sm;\n @include font-size($custom-select-font-size-sm);\n}\n\n.custom-select-lg {\n height: $custom-select-height-lg;\n padding-top: $custom-select-padding-y-lg;\n padding-bottom: $custom-select-padding-y-lg;\n padding-left: $custom-select-padding-x-lg;\n @include font-size($custom-select-font-size-lg);\n}\n\n\n// File\n//\n// Custom file input.\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: $custom-file-height;\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: $custom-file-height;\n margin: 0;\n opacity: 0;\n\n &:focus ~ .custom-file-label {\n border-color: $custom-file-focus-border-color;\n box-shadow: $custom-file-focus-box-shadow;\n }\n\n &:disabled ~ .custom-file-label {\n background-color: $custom-file-disabled-bg;\n }\n\n @each $lang, $value in $custom-file-text {\n &:lang(#{$lang}) ~ .custom-file-label::after {\n content: $value;\n }\n }\n\n ~ .custom-file-label[data-browse]::after {\n content: attr(data-browse);\n }\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: $custom-file-height;\n padding: $custom-file-padding-y $custom-file-padding-x;\n font-family: $custom-file-font-family;\n font-weight: $custom-file-font-weight;\n line-height: $custom-file-line-height;\n color: $custom-file-color;\n background-color: $custom-file-bg;\n border: $custom-file-border-width solid $custom-file-border-color;\n @include border-radius($custom-file-border-radius);\n @include box-shadow($custom-file-box-shadow);\n\n &::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: $custom-file-height-inner;\n padding: $custom-file-padding-y $custom-file-padding-x;\n line-height: $custom-file-line-height;\n color: $custom-file-button-color;\n content: \"Browse\";\n @include gradient-bg($custom-file-button-bg);\n border-left: inherit;\n @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);\n }\n}\n\n// Range\n//\n// Style range inputs the same across browsers. Vendor-specific rules for pseudo\n// elements cannot be mixed. As such, there are no shared styles for focus or\n// active states on prefixed selectors.\n\n.custom-range {\n width: 100%;\n height: calc(#{$custom-range-thumb-height} + #{$custom-range-thumb-focus-box-shadow-width * 2});\n padding: 0; // Need to reset padding\n background-color: transparent;\n appearance: none;\n\n &:focus {\n outline: none;\n\n // Pseudo-elements must be split across multiple rulesets to have an effect.\n // No box-shadow() mixin for focus accessibility.\n &::-webkit-slider-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n &::-moz-range-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n &::-ms-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n }\n\n &::-moz-focus-outer {\n border: 0;\n }\n\n &::-webkit-slider-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n margin-top: ($custom-range-track-height - $custom-range-thumb-height) / 2; // Webkit specific\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-webkit-slider-runnable-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent; // Why?\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent;\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-moz-range-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-moz-range-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent; // Firefox specific?\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n margin-top: 0; // Edge specific\n margin-right: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.\n margin-left: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-ms-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: transparent;\n border-color: transparent;\n border-width: $custom-range-thumb-height / 2;\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-fill-lower {\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n\n &::-ms-fill-upper {\n margin-right: 15px; // arbitrary?\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n\n &:disabled {\n &::-webkit-slider-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n\n &::-webkit-slider-runnable-track {\n cursor: default;\n }\n\n &::-moz-range-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n\n &::-moz-range-track {\n cursor: default;\n }\n\n &::-ms-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n }\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n @include transition($custom-forms-transition);\n}\n","// Base class\n//\n// Kickstart any navigation component with a set of style resets. Works with\n// `