diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index 26c116582f..2c47005dfc 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -69,6 +69,11 @@ parameters: installJdk: true timeoutInMinutes: 180 + # We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case). + # This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build + # timeout due to test hangs. + cancelTimeoutInMinutes: 15 + jobs: - job: ${{ coalesce(parameters.jobName, parameters.agentOs) }} displayName: ${{ coalesce(parameters.jobDisplayName, parameters.agentOs) }} diff --git a/Directory.Build.props b/Directory.Build.props index 06e288aa81..4b87f1845a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -43,7 +43,7 @@ true - netcoreapp$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + netcoreapp$(TFMNetCoreMajorVersion).$(TFMNetCoreMinorVersion) diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt index 96dcfb8ae7..81fadeae22 100644 --- a/THIRD-PARTY-NOTICES.txt +++ b/THIRD-PARTY-NOTICES.txt @@ -164,3 +164,28 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for Angular v8.0 +-------------------------------------------- +The MIT License (MIT) +===================== + +Copyright (c) 2010-2019 Google LLC. http://angular.io/license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/docs/BuildErrors.md b/docs/BuildErrors.md index 52fb8d25de..73bd87d479 100644 --- a/docs/BuildErrors.md +++ b/docs/BuildErrors.md @@ -22,3 +22,12 @@ Similar to BUILD001, but this error is not suppressable. This error only appears This repo uses a common output directory (artifacts/bin/$(ProjectName) and artifacts/obj/$(ProjectName)). To avoid confllicts in build output, each project file should have a unique name. + +### Error MSB4236 / Unable to locate the .NET Core SDK + +Executing `.\restore.cmd` or `.\build.cmd` may produce these errors: + +> error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version. +> error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. + +In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_. diff --git a/docs/BuildFromSource.md b/docs/BuildFromSource.md index d84fe2ab8c..53938c189b 100644 --- a/docs/BuildFromSource.md +++ b/docs/BuildFromSource.md @@ -96,6 +96,15 @@ The cause of this problem is that the solution you are using does not include th dotnet sln add C:\src\AspNetCore\src\Hosting\Abstractions\src\Microsoft.AspNetCore.Hosting.Abstractions.csproj ``` +### Common error: Unable to locate the .NET Core SDK + +Executing `.\restore.cmd` or `.\build.cmd` may produce these errors: + +> error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version. +> error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. + +In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_. + ## Building with Visual Studio Code Using Visual Studio Code with this repo requires setting environment variables on command line first. diff --git a/docs/DailyBuilds.md b/docs/DailyBuilds.md index bc02105131..7e727df9e4 100644 --- a/docs/DailyBuilds.md +++ b/docs/DailyBuilds.md @@ -16,6 +16,7 @@ If you want to download the latest daily build and use it in a project, then you + diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 3f6d8d595c..4d1a3b5c02 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -185,6 +185,8 @@ and are generated based on the last package release. + + diff --git a/eng/GenAPI.exclusions.txt b/eng/GenAPI.exclusions.txt index 3053eb79e1..ebabc0ac7d 100644 --- a/eng/GenAPI.exclusions.txt +++ b/eng/GenAPI.exclusions.txt @@ -2,23 +2,4 @@ T:Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame # Manually implemented - https://github.com/dotnet/arcade/issues/2066 T:Microsoft.AspNetCore.Mvc.ApplicationModels.PageParameterModel -T:Microsoft.AspNetCore.Mvc.ApplicationModels.PagePropertyModel -# Manually implemented - https://github.com/aspnet/AspNetCore/issues/8825 -T:Microsoft.AspNetCore.Components.AuthorizeView -T:Microsoft.AspNetCore.Components.AuthorizeViewCore -T:Microsoft.AspNetCore.Components.CascadingAuthenticationState -T:Microsoft.AspNetCore.Components.CascadingValue`1 -T:Microsoft.AspNetCore.Components.Forms.DataAnnotationsValidator -T:Microsoft.AspNetCore.Components.Forms.EditForm -T:Microsoft.AspNetCore.Components.Forms.InputBase`1 -T:Microsoft.AspNetCore.Components.Forms.InputCheckbox -T:Microsoft.AspNetCore.Components.Forms.InputDate`1 -T:Microsoft.AspNetCore.Components.Forms.InputNumber`1 -T:Microsoft.AspNetCore.Components.Forms.InputSelect`1 -T:Microsoft.AspNetCore.Components.Forms.InputText -T:Microsoft.AspNetCore.Components.Forms.InputTextArea -T:Microsoft.AspNetCore.Components.Forms.ValidationMessage`1 -T:Microsoft.AspNetCore.Components.Forms.ValidationSummary -T:Microsoft.AspNetCore.Components.PageDisplay -T:Microsoft.AspNetCore.Components.Routing.NavLink -T:Microsoft.AspNetCore.Components.Routing.Router \ No newline at end of file +T:Microsoft.AspNetCore.Mvc.ApplicationModels.PagePropertyModel \ No newline at end of file diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index a54507bbb0..5e50238a4b 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -101,7 +101,6 @@ - diff --git a/eng/SharedFramework.Local.props b/eng/SharedFramework.Local.props index a86f138f9f..a52c31e0ad 100644 --- a/eng/SharedFramework.Local.props +++ b/eng/SharedFramework.Local.props @@ -73,7 +73,6 @@ - diff --git a/eng/Signing.props b/eng/Signing.props index 0e8b87b4dd..0dc432069d 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -96,6 +96,12 @@ <_DotNetFilesToExclude Include="$(BaseRedistNetCorePath)win-arm\host\**\*.dll" CertificateName="None" /> <_DotNetFilesToExclude Include="$(RedistNetCorePath)dotnet.exe" CertificateName="None" /> + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8ff491b896..1e7f2fa1cf 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,432 +9,432 @@ --> - + https://github.com/aspnet/Blazor - 9045a3861427fc95575c07bd0455c98731567969 + dd092c2236cf9375b50e19295dd2faf36e6221f6 - + https://github.com/aspnet/AspNetCore-Tooling - d95774f01eb5f86d3f9ad00d2341deb74b024f37 + 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 - + https://github.com/aspnet/AspNetCore-Tooling - d95774f01eb5f86d3f9ad00d2341deb74b024f37 + 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 - + https://github.com/aspnet/AspNetCore-Tooling - d95774f01eb5f86d3f9ad00d2341deb74b024f37 + 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 - + https://github.com/aspnet/AspNetCore-Tooling - d95774f01eb5f86d3f9ad00d2341deb74b024f37 + 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/EntityFrameworkCore - 751fb9dcf92357260128fc55afeb1e1735791297 + 49f9f7632c742108e5652f182922cc35c19c9162 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 https://github.com/dotnet/corefx a28176b5ec68b6da1472934fe9493790d1665cae - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/dotnet/core-setup - 2bb2dcaeffb1dfeda077354449868ddac254bc3d + d15a0adeb874801e7bfaa4fbbb306a2efa268497 - + https://github.com/dotnet/core-setup - 2bb2dcaeffb1dfeda077354449868ddac254bc3d + d15a0adeb874801e7bfaa4fbbb306a2efa268497 - + https://github.com/dotnet/core-setup - 2bb2dcaeffb1dfeda077354449868ddac254bc3d + d15a0adeb874801e7bfaa4fbbb306a2efa268497 - + https://github.com/dotnet/core-setup - 2bb2dcaeffb1dfeda077354449868ddac254bc3d + d15a0adeb874801e7bfaa4fbbb306a2efa268497 - + https://github.com/dotnet/corefx - c14b80faff694bae4e085bad221e2e83410e5f33 + 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/dotnet/arcade - fb27fd4d8a2b67d4333e33d4b898c65171c9f3c1 + a190d4865fe3c86a168ec49c4fc61c90c96ae051 - + https://github.com/dotnet/arcade - fb27fd4d8a2b67d4333e33d4b898c65171c9f3c1 + a190d4865fe3c86a168ec49c4fc61c90c96ae051 - + https://github.com/dotnet/arcade - fb27fd4d8a2b67d4333e33d4b898c65171c9f3c1 + a190d4865fe3c86a168ec49c4fc61c90c96ae051 - + https://github.com/aspnet/Extensions - 8bf6089b4491bc4387cdfec64ab56e7cc39030f8 + 54d000fda95c2c1f05b13a2e910fc91994da8eb8 - + https://github.com/dotnet/roslyn - 342275182023200bcd42b3d9919e984039577b44 + e9b4c66fb2f26bca02d4a718c48c1c39e9963c9f diff --git a/eng/Versions.props b/eng/Versions.props index 6aee4469b6..4f48ab6d95 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,12 +6,12 @@ --> - 3 + 5 0 0 - 8 - preview$(PreReleasePreviewNumber) - Preview $(PreReleasePreviewNumber) + 1 + alpha$(PreReleasePreviewNumber) + Alpha $(PreReleasePreviewNumber) $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) false @@ -38,6 +38,11 @@ false + + + 3 + 0 + - 1.0.0-beta.19365.4 + 1.0.0-beta.19369.2 - 3.3.0-beta2-19363-02 + 3.3.0-beta3-19401-01 - 3.0.0-preview8-27914-06 - 3.0.0-preview8-27914-06 - 3.0.0-preview8-27914-06 - 2.1.0-preview8-27914-06 + 3.0.0-preview8-28379-05 + 3.0.0-preview8-28379-05 + 3.0.0-preview8-28379-05 + 2.1.0-preview8-28379-05 - 1.0.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 + 1.0.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 4.7.0-preview6.19264.9 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 1.7.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 - 4.6.0-preview8.19364.1 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 1.7.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 + 4.6.0-preview8.19378.8 - 3.0.0-preview8.19364.1 + 3.0.0-preview8.19378.8 - 0.10.0-preview8.19365.1 + 5.0.0-alpha1.19403.2 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 - 3.0.0-preview8.19365.1 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 + 3.0.0-preview9.19401.2 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 - 3.0.0-preview8.19365.5 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 + 3.0.0-preview9.19402.9 - 3.0.0-preview8.19365.2 - 3.0.0-preview8.19365.2 - 3.0.0-preview8.19365.2 - 3.0.0-preview8.19365.2 + 5.0.0-alpha1.19381.2 + 5.0.0-alpha1.19381.2 + 5.0.0-alpha1.19381.2 + 5.0.0-alpha1.19381.2 diff --git a/eng/Workarounds.props b/eng/Workarounds.props index e2ad3d58a8..0fa6edaeab 100644 --- a/eng/Workarounds.props +++ b/eng/Workarounds.props @@ -43,4 +43,9 @@ This one sets UseSharedCompilation to false by default. --> true + + + + false + diff --git a/eng/Workarounds.targets b/eng/Workarounds.targets index 83e176a4a8..ed0324f744 100644 --- a/eng/Workarounds.targets +++ b/eng/Workarounds.targets @@ -15,11 +15,6 @@ $(MicrosoftNETCorePlatformsPackageVersion) - - - - - - - - - false - - @@ -47,18 +36,10 @@ - - - - - Microsoft.NETCore.App.Runtime.**RID** - - + + + + NETStandard.Library diff --git a/eng/common/init-tools-native.sh b/eng/common/init-tools-native.sh index fc72d13948..5f2e77f448 100755 --- a/eng/common/init-tools-native.sh +++ b/eng/common/init-tools-native.sh @@ -71,7 +71,7 @@ function ReadGlobalJsonNativeTools { local native_tools_list=$(echo $native_tools_section | awk -F"[{}]" '{print $2}') native_tools_list=${native_tools_list//[\" ]/} native_tools_list=${native_tools_list//,/$'\n'} - native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[:space:]')" + native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[[:space:]]')" local old_IFS=$IFS while read -r line; do diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh index 6098f9a543..1c560a5061 100644 --- a/eng/common/pipeline-logging-functions.sh +++ b/eng/common/pipeline-logging-functions.sh @@ -39,11 +39,11 @@ function Write-PipelineTaskError { return fi - message_type="error" - sourcepath='' - linenumber='' - columnnumber='' - error_code='' + local message_type="error" + local sourcepath='' + local linenumber='' + local columnnumber='' + local error_code='' while [[ $# -gt 0 ]]; do opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" @@ -76,7 +76,7 @@ function Write-PipelineTaskError { shift done - message="##vso[task.logissue" + local message="##vso[task.logissue" message="$message type=$message_type" @@ -100,3 +100,73 @@ function Write-PipelineTaskError { echo "$message" } +function Write-PipelineSetVariable { + if [[ "$ci" != true ]]; then + return + fi + + local name='' + local value='' + local secret=false + local as_output=false + local is_multi_job_variable=true + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -name|-n) + name=$2 + shift + ;; + -value|-v) + value=$2 + shift + ;; + -secret|-s) + secret=true + ;; + -as_output|-a) + as_output=true + ;; + -is_multi_job_variable|-i) + is_multi_job_variable=$2 + shift + ;; + esac + shift + done + + value=${value/;/%3B} + value=${value/\\r/%0D} + value=${value/\\n/%0A} + value=${value/]/%5D} + + local message="##vso[task.setvariable variable=$name;isSecret=$secret;isOutput=$is_multi_job_variable]$value" + + if [[ "$as_output" == true ]]; then + $message + else + echo "$message" + fi +} + +function Write-PipelinePrependPath { + local prepend_path='' + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -path|-p) + prepend_path=$2 + shift + ;; + esac + shift + done + + export PATH="$prepend_path:$PATH" + + if [[ "$ci" == true ]]; then + echo "##vso[task.prependpath]$prepend_path" + fi +} \ No newline at end of file diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 50ad724fc0..648e854e0e 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -84,6 +84,7 @@ stages: /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index 574cb1c2b9..f6a7efdfe9 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -84,6 +84,7 @@ stages: /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 9abaac015f..8fe2b11ad2 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -169,7 +169,7 @@ function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $arc InstallDotNet $dotnetRoot $version $architecture } -function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot +function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ Version = $version diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 70d92cf85a..0deb01c480 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -146,14 +146,10 @@ function InitializeDotNetCli { # Add dotnet to PATH. This prevents any bare invocation of dotnet in custom # build steps from using anything other than what we've downloaded. - export PATH="$dotnet_root:$PATH" + Write-PipelinePrependPath -path "$dotnet_root" - if [[ $ci == true ]]; then - # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build - echo "##vso[task.prependpath]$dotnet_root" - echo "##vso[task.setvariable variable=DOTNET_MULTILEVEL_LOOKUP]0" - echo "##vso[task.setvariable variable=DOTNET_SKIP_FIRST_TIME_EXPERIENCE]1" - fi + Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" + Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" # return value _InitializeDotNetCli="$dotnet_root" @@ -387,7 +383,8 @@ mkdir -p "$toolset_dir" mkdir -p "$temp_dir" mkdir -p "$log_dir" -if [[ $ci == true ]]; then - export TEMP="$temp_dir" - export TMP="$temp_dir" -fi +Write-PipelineSetVariable -name "Artifacts" -value "$artifacts_dir" +Write-PipelineSetVariable -name "Artifacts.Toolset" -value "$toolset_dir" +Write-PipelineSetVariable -name "Artifacts.Log" -value "$log_dir" +Write-PipelineSetVariable -name "Temp" -value "$temp_dir" +Write-PipelineSetVariable -name "TMP" -value "$temp_dir" diff --git a/eng/scripts/dump_process.ps1 b/eng/scripts/dump_process.ps1 index 3c35ea29ee..f3ad56fcf7 100644 --- a/eng/scripts/dump_process.ps1 +++ b/eng/scripts/dump_process.ps1 @@ -1,9 +1,17 @@ Set-Location $args[0] -$timestamp = $(get-date -f MM-dd-HH-mm) - while ($true) { - Get-Process > artifacts/log/runningProcesses.$timestamp.txt - Get-WmiObject Win32_Process | select name, processid, commandline > artifacts/log/runningProcessesCommandLine.$timestamp.txt - Start-Sleep -Seconds 300 -} \ No newline at end of file + $local:file = "artifacts/log/runningProcesses.txt" + if (Test-Path $file) {Move-Item -Force $file "$file.bak"} + + $local:temp = Get-Process |Out-String -Width 300 + $temp.Split([Environment]::NewLine).TrimEnd() |? Length -gt 0 |Out-File -Width 300 $file + + $file = "artifacts/log/runningProcessesCommandLine.txt" + if (Test-Path $file) {Move-Item -Force $file "$file.bak"} + + $temp = Get-CimInstance Win32_Process |Format-Table -AutoSize Name, ProcessId, CommandLine |Out-String -Width 800 + $temp.Split([Environment]::NewLine).TrimEnd() |? Length -gt 0 |Out-File -Width 800 $file + + Start-Sleep -Seconds 120 +} diff --git a/global.json b/global.json index 4c70738470..4f83cb7a89 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "3.0.100-preview6-012264" + "version": "3.0.100-preview7-012821" }, "tools": { - "dotnet": "3.0.100-preview6-012264", + "dotnet": "3.0.100-preview7-012821", "runtimes": { "dotnet/x64": [ "$(MicrosoftNETCoreAppRuntimeVersion)" @@ -24,7 +24,7 @@ }, "msbuild-sdks": { "Yarn.MSBuild": "1.15.2", - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19365.4", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19365.4" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19369.2", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19369.2" } } diff --git a/src/Analyzers/Analyzers/src/BuildServiceProviderAnalzyer.cs b/src/Analyzers/Analyzers/src/BuildServiceProviderAnalyzer.cs similarity index 92% rename from src/Analyzers/Analyzers/src/BuildServiceProviderAnalzyer.cs rename to src/Analyzers/Analyzers/src/BuildServiceProviderAnalyzer.cs index edd78751b9..ecb170ade3 100644 --- a/src/Analyzers/Analyzers/src/BuildServiceProviderAnalzyer.cs +++ b/src/Analyzers/Analyzers/src/BuildServiceProviderAnalyzer.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (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; @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Analyzers if (serviceItem.UseMethod.Name == "BuildServiceProvider") { context.ReportDiagnostic(Diagnostic.Create( - StartupAnalzyer.Diagnostics.BuildServiceProviderShouldNotCalledInConfigureServicesMethod, + StartupAnalyzer.Diagnostics.BuildServiceProviderShouldNotCalledInConfigureServicesMethod, serviceItem.Operation.Syntax.GetLocation(), serviceItem.UseMethod.Name, serviceAnalysis.ConfigureServicesMethod.Name)); diff --git a/src/Analyzers/Analyzers/src/StartupAnalysisBuilder.cs b/src/Analyzers/Analyzers/src/StartupAnalysisBuilder.cs index e5b1217dd7..b7eef9e2d6 100644 --- a/src/Analyzers/Analyzers/src/StartupAnalysisBuilder.cs +++ b/src/Analyzers/Analyzers/src/StartupAnalysisBuilder.cs @@ -10,10 +10,10 @@ namespace Microsoft.AspNetCore.Analyzers internal class StartupAnalysisBuilder { private readonly Dictionary> _analysesByType; - private readonly StartupAnalzyer _analyzer; + private readonly StartupAnalyzer _analyzer; private readonly object _lock; - public StartupAnalysisBuilder(StartupAnalzyer analyzer, StartupSymbols startupSymbols) + public StartupAnalysisBuilder(StartupAnalyzer analyzer, StartupSymbols startupSymbols) { _analyzer = analyzer; StartupSymbols = startupSymbols; diff --git a/src/Analyzers/Analyzers/src/StartupAnalyzer.Diagnostics.cs b/src/Analyzers/Analyzers/src/StartupAnalyzer.Diagnostics.cs index 0a04924177..8ef6205631 100644 --- a/src/Analyzers/Analyzers/src/StartupAnalyzer.Diagnostics.cs +++ b/src/Analyzers/Analyzers/src/StartupAnalyzer.Diagnostics.cs @@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.AspNetCore.Analyzers { - public partial class StartupAnalzyer : DiagnosticAnalyzer + public partial class StartupAnalyzer : DiagnosticAnalyzer { internal static class Diagnostics { diff --git a/src/Analyzers/Analyzers/src/StartupAnalyzer.Events.cs b/src/Analyzers/Analyzers/src/StartupAnalyzer.Events.cs index 9e2a554948..d5004bb432 100644 --- a/src/Analyzers/Analyzers/src/StartupAnalyzer.Events.cs +++ b/src/Analyzers/Analyzers/src/StartupAnalyzer.Events.cs @@ -8,7 +8,7 @@ using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.AspNetCore.Analyzers { // Events for testability. Allows us to unit test the data we gather from analysis. - public partial class StartupAnalzyer : DiagnosticAnalyzer + public partial class StartupAnalyzer : DiagnosticAnalyzer { internal event EventHandler? ConfigureServicesMethodFound; diff --git a/src/Analyzers/Analyzers/src/StartupAnalzyer.cs b/src/Analyzers/Analyzers/src/StartupAnalyzer.cs similarity index 98% rename from src/Analyzers/Analyzers/src/StartupAnalzyer.cs rename to src/Analyzers/Analyzers/src/StartupAnalyzer.cs index 3cbb83c180..6deb7dd53e 100644 --- a/src/Analyzers/Analyzers/src/StartupAnalzyer.cs +++ b/src/Analyzers/Analyzers/src/StartupAnalyzer.cs @@ -9,7 +9,7 @@ using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.AspNetCore.Analyzers { [DiagnosticAnalyzer(LanguageNames.CSharp)] - public partial class StartupAnalzyer : DiagnosticAnalyzer + public partial class StartupAnalyzer : DiagnosticAnalyzer { public override ImmutableArray SupportedDiagnostics => Diagnostics.SupportedDiagnostics; diff --git a/src/Analyzers/Analyzers/src/UseMvcAnalyzer.cs b/src/Analyzers/Analyzers/src/UseMvcAnalyzer.cs index 4cbb702ad1..90c09319bc 100644 --- a/src/Analyzers/Analyzers/src/UseMvcAnalyzer.cs +++ b/src/Analyzers/Analyzers/src/UseMvcAnalyzer.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Analyzers if (!OptionsFacts.IsEndpointRoutingExplicitlyDisabled(optionsAnalysis)) { context.ReportDiagnostic(Diagnostic.Create( - StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, + StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, middlewareItem.Operation.Syntax.GetLocation(), middlewareItem.UseMethod.Name, optionsAnalysis.ConfigureServicesMethod.Name)); diff --git a/src/Analyzers/Analyzers/test/StartupAnalyzerTest.cs b/src/Analyzers/Analyzers/test/StartupAnalyzerTest.cs index c471b56a56..a03cf6cdf2 100644 --- a/src/Analyzers/Analyzers/test/StartupAnalyzerTest.cs +++ b/src/Analyzers/Analyzers/test/StartupAnalyzerTest.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Analyzers { public StartupAnalyzerTest() { - StartupAnalyzer = new StartupAnalzyer(); + StartupAnalyzer = new StartupAnalyzer(); Runner = new AnalyzersDiagnosticAnalyzerRunner(StartupAnalyzer); @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Analyzers StartupAnalyzer.ConfigureMethodFound += (sender, method) => ConfigureMethods.Add(method); } - private StartupAnalzyer StartupAnalyzer { get; } + private StartupAnalyzer StartupAnalyzer { get; } private AnalyzersDiagnosticAnalyzerRunner Runner { get; } @@ -140,7 +140,7 @@ namespace Microsoft.AspNetCore.Analyzers diagnostics, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); }); } @@ -172,7 +172,7 @@ namespace Microsoft.AspNetCore.Analyzers diagnostics, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); }); } @@ -194,17 +194,17 @@ namespace Microsoft.AspNetCore.Analyzers diagnostics, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM1"], diagnostic.Location); }, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM2"], diagnostic.Location); }, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.UnsupportedUseMvcWithEndpointRouting, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM3"], diagnostic.Location); }); } @@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.Analyzers Assert.Collection(diagnostics, diagnostic => { - Assert.Same(StartupAnalzyer.Diagnostics.BuildServiceProviderShouldNotCalledInConfigureServicesMethod, diagnostic.Descriptor); + Assert.Same(StartupAnalyzer.Diagnostics.BuildServiceProviderShouldNotCalledInConfigureServicesMethod, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM1"], diagnostic.Location); }); } diff --git a/src/Analyzers/Analyzers/test/TestFiles/CompilationFeatureDetectorTest/StartupWithMapBlazorHub.cs b/src/Analyzers/Analyzers/test/TestFiles/CompilationFeatureDetectorTest/StartupWithMapBlazorHub.cs index 685483a0b1..764ac23bd5 100644 --- a/src/Analyzers/Analyzers/test/TestFiles/CompilationFeatureDetectorTest/StartupWithMapBlazorHub.cs +++ b/src/Analyzers/Analyzers/test/TestFiles/CompilationFeatureDetectorTest/StartupWithMapBlazorHub.cs @@ -13,8 +13,12 @@ namespace Microsoft.AspNetCore.Analyzers.TestFiles.CompilationFeatureDetectorTes app.UseEndpoints(endpoints => { - endpoints.MapBlazorHub(); + endpoints.MapBlazorHub("app"); }); } + + public class App : Microsoft.AspNetCore.Components.ComponentBase + { + } } } diff --git a/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs b/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs index 0d45edcabc..8df3167b83 100644 --- a/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs +++ b/src/Components/Analyzers/src/ComponentParameterUsageAnalyzer.cs @@ -38,8 +38,18 @@ namespace Microsoft.AspNetCore.Components.Analyzers { startBlockContext.RegisterOperationAction(context => { - var assignmentOperation = (IAssignmentOperation)context.Operation; - var leftHandSide = assignmentOperation.Target; + 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. @@ -96,7 +106,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent, propertyReference.Syntax.GetLocation(), propertyReference.Member.Name)); - }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.CoalesceAssignment); + }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.CoalesceAssignment, OperationKind.Increment, OperationKind.Decrement); }); }); } diff --git a/src/Components/Analyzers/src/DiagnosticDescriptors.cs b/src/Components/Analyzers/src/DiagnosticDescriptors.cs index a34102f39b..e0ecbce055 100644 --- a/src/Components/Analyzers/src/DiagnosticDescriptors.cs +++ b/src/Components/Analyzers/src/DiagnosticDescriptors.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)), new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)), "Encapsulation", - DiagnosticSeverity.Warning, + DiagnosticSeverity.Error, isEnabledByDefault: true, description: new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources))); @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)), new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)), "Encapsulation", - DiagnosticSeverity.Warning, + DiagnosticSeverity.Error, isEnabledByDefault: true, description: new LocalizableResourceString(nameof(Resources.ComponentParametersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources))); diff --git a/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs b/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs index 88b366fd74..f32bc6048e 100644 --- a/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs +++ b/src/Components/Analyzers/test/ComponentParameterSettersShouldBePublicTest.cs @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 39) @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 39) @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 39) diff --git a/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs b/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs index db664a2e76..d1c2d2bede 100644 --- a/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs +++ b/src/Components/Analyzers/test/ComponentParameterUsageAnalyzerTest.cs @@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers class TestComponent : IComponent {{ [Parameter] public string TestProperty {{ get; set; }} + [Parameter] public int TestInt {{ get; set; }} public string NonParameter {{ get; set; }} }} }}" + ComponentsTestDeclarations.Source; @@ -119,6 +120,68 @@ namespace Microsoft.AspNetCore.Components.Analyzers }); } + [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() { diff --git a/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs b/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs index 69a3f2e310..2e1ee00be0 100644 --- a/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs +++ b/src/Components/Analyzers/test/ComponentParametersShouldBePublicCodeFixProviderTest.cs @@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test { Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.BadProperty1' should be public.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 40) @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 39) @@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 39) @@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test { Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 39) diff --git a/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs b/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs index 2f03b9ea31..97b01c4699 100644 --- a/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs +++ b/src/Components/Analyzers/test/ComponentParametersShouldBePublicTest.cs @@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should be public.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 32) @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should be public.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 40) @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should be public.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 42) @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers { Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id, Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty4' should be public.", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 41) diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs index 3897a0bf62..d56360f9aa 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs @@ -1,6 +1,15 @@ // Copyright (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 +{ + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public static partial class JSInteropMethods + { + [Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")] + public static void NotifyLocationChanged(string uri, bool isInterceptedLink) { } + } +} namespace Microsoft.AspNetCore.Blazor.Hosting { public static partial class BlazorWebAssemblyHost @@ -62,24 +71,12 @@ namespace Microsoft.AspNetCore.Blazor.Rendering public override Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get { throw null; } } public System.Threading.Tasks.Task AddComponentAsync(System.Type componentType, string domElementSelector) { throw null; } public System.Threading.Tasks.Task AddComponentAsync(string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; } - public override System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo eventFieldInfo, Microsoft.AspNetCore.Components.UIEventArgs eventArgs) { throw null; } + public override System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo eventFieldInfo, System.EventArgs eventArgs) { throw null; } protected override void Dispose(bool disposing) { } protected override void HandleException(System.Exception exception) { } protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch batch) { throw null; } } } -namespace Microsoft.AspNetCore.Blazor.Services -{ - public partial class WebAssemblyUriHelper : Microsoft.AspNetCore.Components.UriHelperBase - { - internal WebAssemblyUriHelper() { } - public static readonly Microsoft.AspNetCore.Blazor.Services.WebAssemblyUriHelper Instance; - protected override void EnsureInitialized() { } - protected override void NavigateToCore(string uri, bool forceLoad) { } - [Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")] - public static void NotifyLocationChanged(string newAbsoluteUri, bool isInterceptedLink) { } - } -} namespace Microsoft.AspNetCore.Components.Builder { public static partial class ComponentsApplicationBuilderExtensions diff --git a/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs b/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs index 224b731c13..e5631805ef 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/BlazorWebAssemblyHost.cs @@ -4,12 +4,12 @@ namespace Microsoft.AspNetCore.Blazor.Hosting { /// - /// Used to to create instances a Blazor host builder for a Browser application. + /// Used to create an instance of Blazor host builder for a Browser application. /// public static class BlazorWebAssemblyHost { /// - /// Creates a an instance of . + /// Creates an instance of . /// /// The . public static IWebAssemblyHostBuilder CreateDefaultBuilder() diff --git a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs index 0b741cbd22..87bdc951c2 100644 --- a/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs +++ b/src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs @@ -92,16 +92,16 @@ namespace Microsoft.AspNetCore.Blazor.Hosting services.AddSingleton(); services.AddSingleton(WebAssemblyJSRuntime.Instance); services.AddSingleton(); - services.AddSingleton(WebAssemblyUriHelper.Instance); + services.AddSingleton(WebAssemblyNavigationManager.Instance); services.AddSingleton(WebAssemblyNavigationInterception.Instance); services.AddSingleton(); services.AddSingleton(s => { // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it. - var uriHelper = s.GetRequiredService(); + var navigationManager = s.GetRequiredService(); return new HttpClient { - BaseAddress = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri()) + BaseAddress = new Uri(navigationManager.BaseUri) }; }); diff --git a/src/Components/Blazor/Blazor/src/JSInteropMethods.cs b/src/Components/Blazor/Blazor/src/JSInteropMethods.cs new file mode 100644 index 0000000000..239dbb4952 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/JSInteropMethods.cs @@ -0,0 +1,26 @@ +// Copyright (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.ComponentModel; +using Microsoft.AspNetCore.Blazor.Services; +using Microsoft.JSInterop; + +namespace Microsoft.AspNetCore.Blazor +{ + /// + /// Contains methods called by interop. Intended for framework use only, not supported for use in application + /// code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static class JSInteropMethods + { + /// + /// For framework use only. + /// + [JSInvokable(nameof(NotifyLocationChanged))] + public static void NotifyLocationChanged(string uri, bool isInterceptedLink) + { + WebAssemblyNavigationManager.Instance.SetLocation(uri, isInterceptedLink); + } + } +} diff --git a/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs index 528816e492..d4e867621e 100644 --- a/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs +++ b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs @@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering } /// - public override Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo eventFieldInfo, UIEventArgs eventArgs) + public override Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo eventFieldInfo, EventArgs eventArgs) { // Be sure we only run one event handler at once. Although they couldn't run // simultaneously anyway (there's only one thread), they could run nested on @@ -185,10 +185,10 @@ namespace Microsoft.AspNetCore.Blazor.Rendering { public readonly ulong EventHandlerId; public readonly EventFieldInfo EventFieldInfo; - public readonly UIEventArgs EventArgs; + public readonly EventArgs EventArgs; public readonly TaskCompletionSource TaskCompletionSource; - public IncomingEventInfo(ulong eventHandlerId, EventFieldInfo eventFieldInfo, UIEventArgs eventArgs) + public IncomingEventInfo(ulong eventHandlerId, EventFieldInfo eventFieldInfo, EventArgs eventArgs) { EventHandlerId = eventHandlerId; EventFieldInfo = eventFieldInfo; diff --git a/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationInterception.cs b/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationInterception.cs index f7aac51137..74eacbc4f5 100644 --- a/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationInterception.cs +++ b/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationInterception.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Routing; -using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop; +using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop; namespace Microsoft.AspNetCore.Blazor.Services { diff --git a/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationManager.cs b/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationManager.cs new file mode 100644 index 0000000000..9d52c8c9a2 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationManager.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; +using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop; + +namespace Microsoft.AspNetCore.Blazor.Services +{ + /// + /// Default client-side implementation of . + /// + internal class WebAssemblyNavigationManager : NavigationManager + { + /// + /// Gets the instance of . + /// + public static readonly WebAssemblyNavigationManager Instance = new WebAssemblyNavigationManager(); + + // For simplicity we force public consumption of the BrowserNavigationManager through + // a singleton. Only a single instance can be updated by the browser through + // interop. We can construct instances for testing. + internal WebAssemblyNavigationManager() + { + } + + protected override void EnsureInitialized() + { + // As described in the comment block above, BrowserNavigationManager is only for + // client-side (Mono) use, so it's OK to rely on synchronicity here. + var baseUri = WebAssemblyJSRuntime.Instance.Invoke(Interop.GetBaseUri); + var uri = WebAssemblyJSRuntime.Instance.Invoke(Interop.GetLocationHref); + Initialize(baseUri, uri); + } + + public void SetLocation(string uri, bool isInterceptedLink) + { + Uri = uri; + NotifyLocationChanged(isInterceptedLink); + } + + /// + protected override void NavigateToCore(string uri, bool forceLoad) + { + if (uri == null) + { + throw new ArgumentNullException(nameof(uri)); + } + + WebAssemblyJSRuntime.Instance.Invoke(Interop.NavigateTo, uri, forceLoad); + } + } +} diff --git a/src/Components/Blazor/Blazor/src/Services/WebAssemblyUriHelper.cs b/src/Components/Blazor/Blazor/src/Services/WebAssemblyUriHelper.cs deleted file mode 100644 index 957a2e760c..0000000000 --- a/src/Components/Blazor/Blazor/src/Services/WebAssemblyUriHelper.cs +++ /dev/null @@ -1,85 +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; -using Microsoft.JSInterop; -using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop; - -namespace Microsoft.AspNetCore.Blazor.Services -{ - /// - /// Default client-side implementation of . - /// - public class WebAssemblyUriHelper : UriHelperBase - { - /// - /// Gets the instance of . - /// - public static readonly WebAssemblyUriHelper Instance = new WebAssemblyUriHelper(); - - // For simplicity we force public consumption of the BrowserUriHelper through - // a singleton. Only a single instance can be updated by the browser through - // interop. We can construct instances for testing. - internal WebAssemblyUriHelper() - { - } - - protected override void EnsureInitialized() - { - WebAssemblyJSRuntime.Instance.Invoke( - Interop.ListenForNavigationEvents, - typeof(WebAssemblyUriHelper).Assembly.GetName().Name, - nameof(NotifyLocationChanged)); - - // As described in the comment block above, BrowserUriHelper is only for - // client-side (Mono) use, so it's OK to rely on synchronicity here. - var baseUri = WebAssemblyJSRuntime.Instance.Invoke(Interop.GetBaseUri); - var uri = WebAssemblyJSRuntime.Instance.Invoke(Interop.GetLocationHref); - InitializeState(uri, baseUri); - } - - /// - protected override void NavigateToCore(string uri, bool forceLoad) - { - if (uri == null) - { - throw new ArgumentNullException(nameof(uri)); - } - - WebAssemblyJSRuntime.Instance.Invoke(Interop.NavigateTo, uri, forceLoad); - } - - /// - /// For framework use only. - /// - [JSInvokable(nameof(NotifyLocationChanged))] - public static void NotifyLocationChanged(string newAbsoluteUri, bool isInterceptedLink) - { - Instance.SetAbsoluteUri(newAbsoluteUri); - Instance.TriggerOnLocationChanged(isInterceptedLink); - } - - /// - /// Given the document's document.baseURI value, returns the URI - /// that can be prepended to relative URI paths to produce an absolute URI. - /// This is computed by removing anything after the final slash. - /// Internal for tests. - /// - /// The page's document.baseURI value. - /// The URI prefix - internal static string ToBaseUri(string absoluteBaseUri) - { - if (absoluteBaseUri != null) - { - var lastSlashIndex = absoluteBaseUri.LastIndexOf('/'); - if (lastSlashIndex >= 0) - { - return absoluteBaseUri.Substring(0, lastSlashIndex + 1); - } - } - - return "/"; - } - } -} diff --git a/src/Components/Blazor/Blazor/test/WebAssemblyUriHelperTest.cs b/src/Components/Blazor/Blazor/test/WebAssemblyUriHelperTest.cs deleted file mode 100644 index 2903d7fcd3..0000000000 --- a/src/Components/Blazor/Blazor/test/WebAssemblyUriHelperTest.cs +++ /dev/null @@ -1,57 +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.Blazor.Services.Test -{ - public class WebAssemblyUriHelperTest - { - private WebAssemblyUriHelper _uriHelper = new WebAssemblyUriHelper(); - - [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 = WebAssemblyUriHelper.ToBaseUri(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 absoluteUri, string expectedResult) - { - var actualResult = _uriHelper.ToBaseRelativePath(baseUri, absoluteUri); - Assert.Equal(expectedResult, actualResult); - } - - [Theory] - [InlineData("scheme://host/", "otherscheme://host/")] - [InlineData("scheme://host/", "scheme://otherhost/")] - [InlineData("scheme://host/path/", "scheme://host/")] - public void ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri) - { - var ex = Assert.Throws(() => - { - _uriHelper.ToBaseRelativePath(baseUri, absoluteUri); - }); - - Assert.Equal( - $"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.", - ex.Message); - } - } -} diff --git a/src/Components/Blazor/Build/src/ReferenceFromSource.props b/src/Components/Blazor/Build/src/ReferenceFromSource.props index 6c708e4cab..927ec8c757 100644 --- a/src/Components/Blazor/Build/src/ReferenceFromSource.props +++ b/src/Components/Blazor/Build/src/ReferenceFromSource.props @@ -46,12 +46,11 @@ true TargetFramework + + false + + true + TargetFramework + - - - - true - diff --git a/src/Components/Blazor/Build/test/BindRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/BindRazorIntegrationTest.cs index 411b64984b..bc63a4b0df 100644 --- a/src/Components/Blazor/Build/test/BindRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/BindRazorIntegrationTest.cs @@ -68,7 +68,7 @@ namespace Test { public class MyComponent : ComponentBase, IComponent { - Task IComponent.SetParametersAsync(ParameterCollection parameters) + Task IComponent.SetParametersAsync(ParameterView parameters) { return Task.CompletedTask; } @@ -89,7 +89,7 @@ namespace Test frames, frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0), frame => AssertFrame.Attribute(frame, "Value", 42, 1), - frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(EventCallback), 2)); + frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(EventCallback), 2)); } [Fact] @@ -142,7 +142,7 @@ namespace Test { public class MyComponent : ComponentBase, IComponent { - Task IComponent.SetParametersAsync(ParameterCollection parameters) + Task IComponent.SetParametersAsync(ParameterView parameters) { return Task.CompletedTask; } @@ -163,7 +163,7 @@ namespace Test frames, frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0), frame => AssertFrame.Attribute(frame, "Value", 42, 1), - frame => AssertFrame.Attribute(frame, "OnChanged", typeof(EventCallback), 2)); + frame => AssertFrame.Attribute(frame, "OnChanged", typeof(EventCallback), 2)); } [Fact] diff --git a/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs index 8ee3131c1b..90090cb070 100644 --- a/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs @@ -108,7 +108,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 1), + frame => AssertFrame.Attribute(frame, "ChildContent", 1), frame => AssertFrame.Markup(frame, "\n
\n", 2)); } @@ -131,7 +131,7 @@ namespace Test frames, frame => AssertFrame.Component(frame, "Test.RenderChildContentString", 3, 0), frame => AssertFrame.Attribute(frame, "Value", "HI", 1), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 2), + frame => AssertFrame.Attribute(frame, "ChildContent", 2), frame => AssertFrame.MarkupWhitespace(frame, 3), frame => AssertFrame.Element(frame, "div", 2, 4), frame => AssertFrame.Text(frame, "hi", 5), @@ -158,7 +158,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 1), + frame => AssertFrame.Attribute(frame, "ChildContent", 1), frame => AssertFrame.Markup(frame, "\n
\n ", 2)); } @@ -183,10 +183,10 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 1), + frame => AssertFrame.Attribute(frame, "ChildContent", 1), frame => AssertFrame.MarkupWhitespace(frame, 2), frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 3), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 4), + frame => AssertFrame.Attribute(frame, "ChildContent", 4), frame => AssertFrame.MarkupWhitespace(frame, 6), frame => AssertFrame.Markup(frame, "\n
\n ", 5)); } @@ -208,7 +208,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3), + frame => AssertFrame.Attribute(frame, "ChildContent", 3), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "hi", 1)); } @@ -230,7 +230,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContentString", 3, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3), + frame => AssertFrame.Attribute(frame, "ChildContent", 3), frame => AssertFrame.Attribute(frame, "Value", "HI", 4), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "hi", 1)); @@ -253,7 +253,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3), + frame => AssertFrame.Attribute(frame, "ChildContent", 3), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "hi", 1)); } @@ -275,7 +275,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3), + frame => AssertFrame.Attribute(frame, "ChildContent", 3), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "hi", 1)); } @@ -299,7 +299,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3), + frame => AssertFrame.Attribute(frame, "ChildContent", 3), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "hi", 1)); } @@ -327,7 +327,7 @@ namespace Test frame => AssertFrame.Attribute(frame, "Name", "billg", 3), frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment), 4), frame => AssertFrame.Attribute(frame, "Value", "HI", 5), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, typeof(RenderFragment), 6), + frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment), 6), frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10), frame => AssertFrame.Element(frame, "div", 2, 0), frame => AssertFrame.Text(frame, "billg", 1), @@ -360,7 +360,7 @@ namespace Test frame => AssertFrame.Attribute(frame, "Name", "billg", 1), frame => AssertFrame.Attribute(frame, "Value", "HI", 2), frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment), 3), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, typeof(RenderFragment), 6), + frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment), 6), frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10), frame => AssertFrame.Element(frame, "div", 2, 4), frame => AssertFrame.Text(frame, "billg", 5), @@ -395,7 +395,7 @@ namespace Test frame => AssertFrame.Attribute(frame, "Name", "billg", 1), frame => AssertFrame.Attribute(frame, "Value", "HI", 2), frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment), 3), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, typeof(RenderFragment), 6), + frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment), 6), frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10), frame => AssertFrame.Element(frame, "div", 2, 4), frame => AssertFrame.Text(frame, "billg", 5), diff --git a/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs index 7ecb5e4554..6c0a7fab96 100644 --- a/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs @@ -165,7 +165,7 @@ namespace Test { public class MyComponent : ComponentBase, IComponent { - Task IComponent.SetParametersAsync(ParameterCollection parameters) + Task IComponent.SetParametersAsync(ParameterView parameters) { return Task.CompletedTask; } @@ -253,7 +253,7 @@ namespace Test public class MyComponent : ComponentBase { [Parameter] - public Action OnClick { get; set; } + public Action OnClick { get; set; } } } ")); @@ -263,7 +263,7 @@ namespace Test @code { private int counter; - private void Increment(UIEventArgs e) { + private void Increment(EventArgs e) { counter++; } }"); @@ -280,7 +280,7 @@ namespace Test AssertFrame.Attribute(frame, "OnClick", 1); // The handler will have been assigned to a lambda - var handler = Assert.IsType>(frame.AttributeValue); + var handler = Assert.IsType>(frame.AttributeValue); Assert.Equal("Test.TestComponent", handler.Target.GetType().FullName); Assert.Equal("Increment", handler.Method.Name); }); @@ -345,7 +345,7 @@ namespace Test frames, frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0), frame => AssertFrame.Attribute(frame, "MyAttr", "abc", 1), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 2)); + frame => AssertFrame.Attribute(frame, "ChildContent", 2)); // Assert: Captured ChildContent frames are correct var childFrames = GetFrames((RenderFragment)frames[2].AttributeValue); @@ -385,7 +385,7 @@ namespace Test Assert.Collection( frames, frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 1)); + frame => AssertFrame.Attribute(frame, "ChildContent", 1)); // Assert: first level of ChildContent is correct // Note that we don't really need the sequence numbers to continue on from the @@ -397,7 +397,7 @@ namespace Test Assert.Collection( innerFrames, frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 2), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 3)); + frame => AssertFrame.Attribute(frame, "ChildContent", 3)); // Assert: second level of ChildContent is correct Assert.Collection( @@ -540,7 +540,7 @@ namespace Test frame => AssertFrame.Element(frame, "body", 5, 3), frame => AssertFrame.MarkupWhitespace(frame, 4), frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 5), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 6), + frame => AssertFrame.Attribute(frame, "ChildContent", 6), frame => AssertFrame.MarkupWhitespace(frame, 16), frame => AssertFrame.MarkupWhitespace(frame, 17)); diff --git a/src/Components/Blazor/Build/test/DirectiveRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/DirectiveRazorIntegrationTest.cs index de2cc72807..ef46dd1d19 100644 --- a/src/Components/Blazor/Build/test/DirectiveRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/DirectiveRazorIntegrationTest.cs @@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test { } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { return Task.CompletedTask; } diff --git a/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs index ed03db31ab..45c178e4bb 100644 --- a/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs @@ -170,7 +170,7 @@ namespace Test frames, frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0), frame => AssertFrame.Attribute(frame, "Items", typeof(List), 1), - frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 2), + frame => AssertFrame.Attribute(frame, "ChildContent", 2), frame => AssertFrame.MarkupWhitespace(frame, 3), frame => AssertFrame.Element(frame, "div", 2, 4), frame => AssertFrame.Text(frame, "0", 5), diff --git a/src/Components/Blazor/Build/test/RazorIntegrationTestBase.cs b/src/Components/Blazor/Build/test/RazorIntegrationTestBase.cs index 8eda2e6b35..943a658a36 100644 --- a/src/Components/Blazor/Build/test/RazorIntegrationTestBase.cs +++ b/src/Components/Blazor/Build/test/RazorIntegrationTestBase.cs @@ -385,7 +385,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test protected private RenderTreeFrame[] GetRenderTree(TestRenderer renderer, IComponent component) { renderer.AttachComponent(component); - var task = renderer.Dispatcher.InvokeAsync(() => component.SetParametersAsync(ParameterCollection.Empty)); + var task = renderer.Dispatcher.InvokeAsync(() => component.SetParametersAsync(ParameterView.Empty)); // we will have to change this method if we add a test that does actual async work. Assert.True(task.Status.HasFlag(TaskStatus.RanToCompletion) || task.Status.HasFlag(TaskStatus.Faulted)); if (task.IsFaulted) @@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test protected ArrayRange GetFrames(RenderFragment fragment) { - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); fragment(builder); return builder.GetFrames(); } diff --git a/src/Components/Blazor/Build/test/RenderingRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/RenderingRazorIntegrationTest.cs index 8b91c024b4..990ec1db18 100644 --- a/src/Components/Blazor/Build/test/RenderingRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/RenderingRazorIntegrationTest.cs @@ -332,7 +332,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Trigger the change event to show it updates the property // // This should always complete synchronously. - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = "Modified value", })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = "Modified value", })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; @@ -367,7 +367,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Trigger the change event to show it updates the property // // This should always complete synchronously. - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = "Modified value", })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = "Modified value", })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; @@ -404,7 +404,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // // This should always complete synchronously. var newDateValue = new DateTime(2018, 3, 5, 4, 5, 6); - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = newDateValue.ToString(), })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = newDateValue.ToString(), })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; @@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Trigger the change event to show it updates the property // // This should always complete synchronously. - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = new DateTime(2018, 3, 5).ToString(testDateFormat), })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = new DateTime(2018, 3, 5).ToString(testDateFormat), })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; @@ -559,7 +559,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Trigger the change event to show it updates the property // // This should always complete synchronously. - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs() { Value = false, })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs() { Value = false, })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; @@ -595,7 +595,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Trigger the change event to show it updates the property // // This should always complete synchronously. - var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = MyEnum.SecondValue.ToString(), })); + var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = MyEnum.SecondValue.ToString(), })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; diff --git a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj b/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj index b0120ab08b..c91a32128d 100644 --- a/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj +++ b/src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj @@ -1,5 +1,4 @@ - - + netstandard2.0 Microsoft.AspNetCore.Blazor.Templates.nuspec @@ -16,18 +15,31 @@ false - - + + + + + <_TemplateConfigMainFile Include="content\**\.template.config.src\template.json" /> - <_TemplateConfigDir Include="@(_TemplateConfigMainFile->'$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigMainFile.FullPath)'))')" /> + <_TemplateConfigDir Include="@(_TemplateConfigMainFile->'$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigMainFile.FullPath)'))')" /> <_TemplateConfigFileToCopy Include="%(_TemplateConfigDir.Identity)\**\*.*"> $([System.IO.Path]::GetDirectoryName('%(_TemplateConfigDir.Identity)'))\.template.config\ + + + + + @@ -49,8 +61,4 @@ - - - - diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json index 96d177267c..755c0a8ad7 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json @@ -5,6 +5,7 @@ "Blazor", "WebAssembly" ], + "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", "guids": [ diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor index eb5c93b6de..c5ee6a53e2 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor @@ -1,5 +1,5 @@  - +

Sorry, there's nothing at this address.

-
+
diff --git a/src/Components/Blazor/testassets/StandaloneApp/Pages/FetchData.razor b/src/Components/Blazor/testassets/StandaloneApp/Pages/FetchData.razor index 9a741bddfb..c640fe9fbc 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/Pages/FetchData.razor +++ b/src/Components/Blazor/testassets/StandaloneApp/Pages/FetchData.razor @@ -34,36 +34,32 @@ else

- + ◀ Previous - + Next ▶

} @code { - [Parameter] public DateTime StartDate { get; set; } + [Parameter] public DateTime? StartDate { get; set; } WeatherForecast[] forecasts; - - public override Task SetParametersAsync(ParameterCollection parameters) - { - StartDate = DateTime.Now; - return base.SetParametersAsync(parameters); - } + DateTime startDate; protected override async Task OnParametersSetAsync() { + startDate = StartDate.GetValueOrDefault(DateTime.Now); forecasts = await Http.GetJsonAsync( - $"sample-data/weather.json?date={StartDate.ToString("yyyy-MM-dd")}"); + $"sample-data/weather.json?date={startDate.ToString("yyyy-MM-dd")}"); // Because StandaloneApp doesn't really have a server endpoint to get dynamic data from, // fake the DateFormatted values here. This would not apply in a real app. for (var i = 0; i < forecasts.Length; i++) { - forecasts[i].DateFormatted = StartDate.AddDays(i).ToShortDateString(); + forecasts[i].DateFormatted = startDate.AddDays(i).ToShortDateString(); } } diff --git a/src/Components/Components.sln b/src/Components/Components.sln index 386152c3d8..e80d4396f9 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -208,8 +208,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\..\.editorconfig = ..\..\.editorconfig EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Components.Prerendering", "..\Mvc\Mvc.Components.Prerendering\src\Microsoft.AspNetCore.Mvc.Components.Prerendering.csproj", "{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}" -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}" @@ -226,6 +224,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor 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 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1328,18 +1328,6 @@ Global {9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x64.Build.0 = Debug|Any CPU {9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.ActiveCfg = Debug|Any CPU {9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.Build.0 = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.ActiveCfg = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.Build.0 = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.ActiveCfg = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.Build.0 = Debug|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.Build.0 = Release|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.ActiveCfg = Release|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.Build.0 = Release|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.ActiveCfg = Release|Any CPU - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.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 @@ -1436,6 +1424,18 @@ Global {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1534,7 +1534,6 @@ Global {04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102} {DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102} {9088E4E4-B855-457F-AE9E-D86709A5E1F4} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {3A4132B6-60DA-43A0-8E7B-4BF346F3247C} = {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} @@ -1543,6 +1542,7 @@ Global {FC2A1EB0-A116-4689-92B7-239B1DCCF4CA} = {E9E9CF3C-CE9B-4282-B2BB-97EFC3872798} {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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE} diff --git a/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs b/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs index d48b4026ab..51d7fea9fc 100644 --- a/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs +++ b/src/Components/Components/perf/RenderTreeDiffBuilderBenchmark.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Components.Performance // 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(renderer); + original = new RenderTreeBuilder(); original.OpenElement(0, "div"); original.AddAttribute(1, "class", "form-group"); @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Components.Performance original.CloseElement(); // Now simulate some input - modified = new RenderTreeBuilder(renderer); + modified = new RenderTreeBuilder(); modified.OpenElement(0, "div"); modified.AddAttribute(1, "class", "form-group"); 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 index be1a95b1dd..ed14f101cd 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree [System.Runtime.InteropServices.FieldOffsetAttribute(16)] public readonly string ElementName; [System.Runtime.InteropServices.FieldOffsetAttribute(24)] - public readonly System.Action ElementReferenceCaptureAction; + public readonly System.Action ElementReferenceCaptureAction; [System.Runtime.InteropServices.FieldOffsetAttribute(16)] public readonly string ElementReferenceCaptureId; [System.Runtime.InteropServices.FieldOffsetAttribute(8)] @@ -45,235 +45,3 @@ namespace Microsoft.AspNetCore.Components.RenderTree public override string ToString() { throw null; } } } - -// Built-in components: https://github.com/aspnet/AspNetCore/issues/8825 -namespace Microsoft.AspNetCore.Components -{ - public partial class AuthorizeView : Microsoft.AspNetCore.Components.AuthorizeViewCore - { - public AuthorizeView() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Policy { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Roles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - protected override Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData() { throw null; } - } - - public abstract partial class AuthorizeViewCore : Microsoft.AspNetCore.Components.ComponentBase - { - public AuthorizeViewCore() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.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; } private set { throw null; } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override void OnInitialized() { } - void System.IDisposable.Dispose() { } - } - - 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; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public bool IsFixed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public T Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters) { throw null; } - } - - public partial class PageDisplay : Microsoft.AspNetCore.Components.IComponent - { - public PageDisplay() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment AuthorizingContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorizedContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type Page { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Collections.Generic.IDictionary PageParameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters) { throw null; } - } -} - -namespace Microsoft.AspNetCore.Components.Forms -{ - public partial class DataAnnotationsValidator : Microsoft.AspNetCore.Components.ComponentBase - { - public DataAnnotationsValidator() { } - protected override void OnInitialized() { } - } - - public partial class EditForm : Microsoft.AspNetCore.Components.ComponentBase - { - public EditForm() { } - [Parameter(CaptureUnmatchedValues = true)] - public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.EventCallback OnInvalidSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.EventCallback OnSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.EventCallback OnValidSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override void OnParametersSet() { } - } - - public abstract partial class InputBase : Microsoft.AspNetCore.Components.ComponentBase - { - protected InputBase() { } - [Parameter(CaptureUnmatchedValues = true)] - public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected string CssClass { get { throw null; } } - protected T CurrentValue { get { throw null; } set { } } - protected string CurrentValueAsString { get { throw null; } set { } } - protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - protected string FieldClass { get { throw null; } } - protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public T Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.EventCallback ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Linq.Expressions.Expression> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected virtual string FormatValueAsString(T value) { throw null; } - public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters) { throw null; } - protected abstract bool TryParseValueFromString(string value, out T result, out string validationErrorMessage); - } - - public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputCheckbox() { } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override bool TryParseValueFromString(string value, out bool result, out string validationErrorMessage) { throw null; } - } - - public partial class InputDate : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputDate() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override string FormatValueAsString(T value) { throw null; } - protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } - } - - public partial class InputNumber : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputNumber() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } - } - - public partial class InputSelect : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputSelect() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } - } - - public partial class InputText : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputText() { } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) { throw null; } - } - - public partial class InputTextArea : Microsoft.AspNetCore.Components.Forms.InputBase - { - public InputTextArea() { } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) { throw null; } - } - - public partial class ValidationMessage : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - public ValidationMessage() { } - [Parameter(CaptureUnmatchedValues = true)] - public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Linq.Expressions.Expression> For { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override void OnParametersSet() { } - void System.IDisposable.Dispose() { } - } - - public partial class ValidationSummary : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable - { - public ValidationSummary() { } - [Parameter(CaptureUnmatchedValues = true)] - public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } - protected override void OnParametersSet() { } - void System.IDisposable.Dispose() { } - } -} - -namespace Microsoft.AspNetCore.Components.Routing -{ - public partial class NavLink : Microsoft.AspNetCore.Components.IComponent, System.IDisposable - { - public NavLink() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public string ActiveClass { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues = true)] - public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get; private set; } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public RenderFragment ChildContent { get; set; } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.Routing.NavLinkMatch Match { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public void Dispose() { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters) { throw null; } - } - - public partial class Router : Microsoft.AspNetCore.Components.IComponent, System.IDisposable - { - public Router() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotFoundContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorizedContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment AuthorizingContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }} - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public void Dispose() { } - protected virtual void Render(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, System.Type handler, System.Collections.Generic.IDictionary parameters) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters) { throw 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 index 9cf260bf92..4f317be0ff 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs @@ -16,14 +16,32 @@ namespace Microsoft.AspNetCore.Components public abstract System.Threading.Tasks.Task GetAuthenticationStateAsync(); protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task task) { } } - [Microsoft.AspNetCore.Components.BindElementAttribute("select", null, "value", "onchange")] - [Microsoft.AspNetCore.Components.BindElementAttribute("textarea", null, "value", "onchange")] - [Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange")] - [Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange")] - [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange")] - [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange")] - public static partial class BindAttributes + public partial class AuthorizeView : Microsoft.AspNetCore.Components.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.RenderTree.RenderTreeBuilder builder) { } + protected abstract Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData(); + [System.Diagnostics.DebuggerStepThroughAttribute] + protected override System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } } public static partial class BindConverter { @@ -72,31 +90,14 @@ namespace Microsoft.AspNetCore.Components 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 partial class CascadingAuthenticationState : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { - 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.Class, AllowMultiple=true, Inherited=true)] - public sealed partial class BindInputElementAttribute : System.Attribute - { - public BindInputElementAttribute(string type, string suffix, string valueAttribute, string changeAttribute) { } - public string ChangeAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Suffix { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public string ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - public static partial class BindMethods - { - public static string GetValue(System.DateTime value, string format) { throw null; } - public static string GetValue(System.DateTimeOffset value, string format) { throw null; } - public static string GetValue(System.DateTimeOffset? value, string format) { throw null; } - public static string GetValue(System.DateTime? value, string format) { throw null; } - public static T GetValue(T value) { throw null; } + 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.RenderTree.RenderTreeBuilder builder) { } + protected override void OnInitialized() { } + void System.IDisposable.Dispose() { } } [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] public sealed partial class CascadingParameterAttribute : System.Attribute @@ -104,6 +105,25 @@ namespace Microsoft.AspNetCore.Components 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 T 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() { } @@ -119,19 +139,10 @@ namespace Microsoft.AspNetCore.Components 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.ParameterCollection parameters) { 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 partial class DataTransfer - { - public DataTransfer() { } - public string DropEffect { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string EffectAllowed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string[] Files { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Components.UIDataTransferItem[] Items { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string[] Types { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } public abstract partial class Dispatcher { protected Dispatcher() { } @@ -144,13 +155,6 @@ namespace Microsoft.AspNetCore.Components protected void OnUnhandledException(System.UnhandledExceptionEventArgs e) { } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct ElementRef - { - private readonly object _dummy; - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public string __internalId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct ElementReference { private readonly object _dummy; @@ -189,55 +193,35 @@ namespace Microsoft.AspNetCore.Components } 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 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 EventCallbackFactoryUIEventArgsExtensions + 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.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.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.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.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.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; } - 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; } - 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; } - 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; } - 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; } - 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; } + 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 @@ -256,111 +240,10 @@ namespace Microsoft.AspNetCore.Components public bool HasDelegate { get { throw null; } } public System.Threading.Tasks.Task InvokeAsync(T 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 string AttributeName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public System.Type EventArgsType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - } - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onabort", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onactivate", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforeactivate", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforecopy", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforecut", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforedeactivate", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforepaste", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onblur", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncanplay", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncanplaythrough", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onchange", typeof(Microsoft.AspNetCore.Components.UIChangeEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onclick", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncontextmenu", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncopy", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncuechange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncut", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondblclick", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondeactivate", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondrag", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragend", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragenter", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragleave", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragover", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragstart", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondrop", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondurationchange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onemptied", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onended", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onerror", typeof(Microsoft.AspNetCore.Components.UIErrorEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocus", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocusin", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocusout", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfullscreenchange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfullscreenerror", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ongotpointercapture", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oninput", typeof(Microsoft.AspNetCore.Components.UIChangeEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("oninvalid", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeydown", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeypress", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeyup", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onload", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadeddata", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadedmetadata", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadend", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadstart", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onlostpointercapture", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousedown", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousemove", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseout", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseover", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseup", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousewheel", typeof(Microsoft.AspNetCore.Components.UIWheelEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpaste", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpause", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onplay", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onplaying", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointercancel", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerdown", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerenter", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerleave", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerlockchange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerlockerror", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointermove", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerout", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerover", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerup", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onprogress", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onratechange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onreadystatechange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onreset", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onscroll", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onseeked", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onseeking", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselect", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselectionchange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselectstart", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onstalled", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onstop", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onsubmit", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onsuspend", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontimeout", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontimeupdate", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchcancel", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchend", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchenter", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchleave", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchmove", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchstart", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onvolumechange", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onwaiting", typeof(Microsoft.AspNetCore.Components.UIEventArgs))] - [Microsoft.AspNetCore.Components.EventHandlerAttribute("onwheel", typeof(Microsoft.AspNetCore.Components.UIWheelEventArgs))] - public static partial class EventHandlers - { - } public partial interface IComponent { void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle); - System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterCollection parameters); + System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters); } public partial interface IComponentContext { @@ -374,21 +257,15 @@ namespace Microsoft.AspNetCore.Components { System.Threading.Tasks.Task HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem item, object arg); } + public partial interface IHostEnvironmentAuthenticationStateProvider + { + void SetAuthenticationState(System.Threading.Tasks.Task authenticationStateTask); + } [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] public sealed partial class InjectAttribute : System.Attribute { public InjectAttribute() { } } - public partial interface IUriHelper - { - event System.EventHandler OnLocationChanged; - string GetAbsoluteUri(); - string GetBaseUri(); - void NavigateTo(string uri); - void NavigateTo(string uri, bool forceLoad); - System.Uri ToAbsoluteUri(string href); - string ToBaseRelativePath(string baseUri, string locationAbsolute); - } [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)] public sealed partial class LayoutAttribute : System.Attribute { @@ -399,7 +276,11 @@ namespace Microsoft.AspNetCore.Components { protected LayoutComponentBase() { } [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + 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 @@ -415,14 +296,46 @@ namespace Microsoft.AspNetCore.Components public NavigationException(string uri) { } public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct Parameter + public abstract partial class NavigationManager { - 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; } } + 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; } } + } + public partial class PageDisplay : Microsoft.AspNetCore.Components.IComponent + { + public PageDisplay() { } + [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 { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Type Page { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Collections.Generic.IDictionary PageParameters { [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; } } [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] public sealed partial class ParameterAttribute : System.Attribute @@ -431,29 +344,35 @@ namespace Microsoft.AspNetCore.Components 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 ParameterCollection + public readonly partial struct ParameterValue { private readonly object _dummy; private readonly int _dummyPrimitive; - public static Microsoft.AspNetCore.Components.ParameterCollection Empty { get { throw null; } } - public static Microsoft.AspNetCore.Components.ParameterCollection FromDictionary(System.Collections.Generic.IDictionary parameters) { throw null; } - public Microsoft.AspNetCore.Components.ParameterEnumerator GetEnumerator() { throw null; } - public T GetValueOrDefault(string parameterName) { throw null; } - public T GetValueOrDefault(string parameterName, T defaultValue) { throw null; } - public System.Collections.Generic.IReadOnlyDictionary ToDictionary() { throw null; } - public bool TryGetValue(string parameterName, out T result) { throw null; } - } - public static partial class ParameterCollectionExtensions - { - public static void SetParameterProperties(this in Microsoft.AspNetCore.Components.ParameterCollection parameterCollection, object target) { } + 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 partial struct ParameterEnumerator + public readonly partial struct ParameterView { - private object _dummy; - private int _dummyPrimitive; - public Microsoft.AspNetCore.Components.Parameter Current { get { throw null; } } - public bool MoveNext() { throw null; } + 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 T GetValueOrDefault(string parameterName) { throw null; } + public T GetValueOrDefault(string parameterName, T defaultValue) { throw null; } + public void SetParameterProperties(object target) { } + public System.Collections.Generic.IReadOnlyDictionary ToDictionary() { throw null; } + public bool TryGetValue(string parameterName, out T 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.RenderTree.RenderTreeBuilder builder); public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(T value); @@ -472,154 +391,23 @@ namespace Microsoft.AspNetCore.Components public RouteAttribute(string template) { } public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { 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; } } - public partial class UIChangeEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIChangeEventArgs() { } - public object Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIClipboardEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIClipboardEventArgs() { } - } - public partial class UIDataTransferItem - { - public UIDataTransferItem() { } - public string Kind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIDragEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs - { - public UIDragEventArgs() { } - public Microsoft.AspNetCore.Components.DataTransfer DataTransfer { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIErrorEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIErrorEventArgs() { } - public int Colno { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string Filename { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public int Lineno { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string Message { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIEventArgs - { - public static readonly Microsoft.AspNetCore.Components.UIEventArgs Empty; - public UIEventArgs() { } - public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIFocusEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIFocusEventArgs() { } - } - public partial class UIKeyboardEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIKeyboardEventArgs() { } - public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string Code { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string Key { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public float Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool Repeat { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIMouseEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIMouseEventArgs() { } - public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Button { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Buttons { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ClientX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ClientY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Detail { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ScreenX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ScreenY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIPointerEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs - { - public UIPointerEventArgs() { } - public float Height { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool IsPrimary { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long PointerId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public string PointerType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public float Pressure { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public float TiltX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public float TiltY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public float Width { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIProgressEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UIProgressEventArgs() { } - public bool LengthComputable { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Loaded { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Total { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UITouchEventArgs : Microsoft.AspNetCore.Components.UIEventArgs - { - public UITouchEventArgs() { } - public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Components.UITouchPoint[] ChangedTouches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Detail { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Components.UITouchPoint[] TargetTouches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Components.UITouchPoint[] Touches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UITouchPoint - { - public UITouchPoint() { } - public double ClientX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ClientY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public long Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double PageX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double PageY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ScreenX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double ScreenY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class UIWheelEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs - { - public UIWheelEventArgs() { } - public long DeltaMode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double DeltaX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double DeltaY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public double DeltaZ { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public abstract partial class UriHelperBase : Microsoft.AspNetCore.Components.IUriHelper - { - protected UriHelperBase() { } - public event System.EventHandler OnLocationChanged { add { } remove { } } - protected virtual void EnsureInitialized() { } - public string GetAbsoluteUri() { throw null; } - public virtual string GetBaseUri() { throw null; } - public virtual void InitializeState(string uriAbsolute, string baseUriAbsolute) { } - public void NavigateTo(string uri) { } - public void NavigateTo(string uri, bool forceLoad) { } - protected abstract void NavigateToCore(string uri, bool forceLoad); - protected void SetAbsoluteBaseUri(string baseUri) { } - protected void SetAbsoluteUri(string uri) { } - public System.Uri ToAbsoluteUri(string href) { throw null; } - public string ToBaseRelativePath(string baseUri, string locationAbsolute) { throw null; } - protected void TriggerOnLocationChanged(bool isinterceptedLink) { } - } -} -namespace Microsoft.AspNetCore.Components.CompilerServices -{ - public static partial class RuntimeHelpers - { - public static T TypeCheck(T value) { throw null; } - } } 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) { } @@ -630,8 +418,10 @@ namespace Microsoft.AspNetCore.Components.Forms 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) { } @@ -642,29 +432,20 @@ namespace Microsoft.AspNetCore.Components.Forms { public static Microsoft.AspNetCore.Components.Forms.EditContext AddDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext) { throw null; } } - public static partial class EditContextExpressionExtensions + public sealed partial class FieldChangedEventArgs : System.EventArgs { - public static System.Collections.Generic.IEnumerable GetValidationMessages(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, System.Linq.Expressions.Expression> accessor) { throw null; } - public static bool IsModified(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, System.Linq.Expressions.Expression> accessor) { throw null; } - } - public static partial class EditContextFieldClassExtensions - { - public static string FieldClass(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } - public static string FieldClass(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, System.Linq.Expressions.Expression> accessor) { throw null; } - } - public sealed partial class FieldChangedEventArgs - { - internal FieldChangedEventArgs() { } + 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 + 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; } } @@ -673,24 +454,23 @@ namespace Microsoft.AspNetCore.Components.Forms 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 AddRange(in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier, System.Collections.Generic.IEnumerable messages) { } + 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 static partial class ValidationMessageStoreExpressionExtensions + public sealed partial class ValidationRequestedEventArgs : System.EventArgs { - public static void Add(this Microsoft.AspNetCore.Components.Forms.ValidationMessageStore store, System.Linq.Expressions.Expression> accessor, string message) { } - public static void AddRange(this Microsoft.AspNetCore.Components.Forms.ValidationMessageStore store, System.Linq.Expressions.Expression> accessor, System.Collections.Generic.IEnumerable messages) { } - public static void Clear(this Microsoft.AspNetCore.Components.Forms.ValidationMessageStore store, System.Linq.Expressions.Expression> accessor) { } + public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationRequestedEventArgs Empty; + public ValidationRequestedEventArgs() { } } - public sealed partial class ValidationRequestedEventArgs + public sealed partial class ValidationStateChangedEventArgs : System.EventArgs { - internal ValidationRequestedEventArgs() { } - } - public sealed partial class ValidationStateChangedEventArgs - { - internal ValidationStateChangedEventArgs() { } + public static readonly new Microsoft.AspNetCore.Components.Forms.ValidationStateChangedEventArgs Empty; + public ValidationStateChangedEventArgs() { } } } namespace Microsoft.AspNetCore.Components.Rendering @@ -715,8 +495,8 @@ namespace Microsoft.AspNetCore.Components.Rendering public override Microsoft.AspNetCore.Components.Dispatcher Dispatcher { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override void HandleException(System.Exception exception) { } [System.Diagnostics.DebuggerStepThroughAttribute] - public System.Threading.Tasks.Task RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterCollection initialParameters) { throw null; } - public System.Threading.Tasks.Task RenderComponentAsync(Microsoft.AspNetCore.Components.ParameterCollection initialParameters) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; } + public System.Threading.Tasks.Task RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; } + public System.Threading.Tasks.Task RenderComponentAsync(Microsoft.AspNetCore.Components.ParameterView initialParameters) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; } protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch renderBatch) { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] @@ -735,14 +515,14 @@ namespace Microsoft.AspNetCore.Components.Rendering public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } protected internal virtual void AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } - public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, Microsoft.AspNetCore.Components.UIEventArgs eventArgs) { throw null; } + public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } protected abstract void HandleException(System.Exception exception); protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; } protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId) { throw null; } [System.Diagnostics.DebuggerStepThroughAttribute] - protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterCollection initialParameters) { throw null; } + 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.Rendering.RenderBatch renderBatch); } } @@ -768,15 +548,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree public ArrayRange(T[] array, int count) { throw null; } public Microsoft.AspNetCore.Components.RenderTree.ArrayRange Clone() { throw null; } } - public partial class RenderTreeBuilder : System.IDisposable + public sealed partial class RenderTreeBuilder : System.IDisposable { - public const string ChildContent = "ChildContent"; - public RenderTreeBuilder(Microsoft.AspNetCore.Components.Rendering.Renderer renderer) { } + 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, System.Action value) { } public void AddAttribute(int sequence, string name, bool value) { } - public void AddAttribute(int sequence, string name, System.Func 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) { } @@ -787,16 +564,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree public void AddContent(int sequence, object textContent) { } public void AddContent(int sequence, string textContent) { } public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment, T value) { } - public void AddElementReferenceCapture(int sequence, System.Action elementReferenceCaptureAction) { } + 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() { } @@ -849,22 +628,35 @@ namespace Microsoft.AspNetCore.Components.RenderTree } namespace Microsoft.AspNetCore.Components.Routing { + public partial interface IHostEnvironmentNavigationManager + { + void Initialize(string baseUri, string uri); + } public partial interface INavigationInterception { System.Threading.Tasks.Task EnableNavigationInterceptionAsync(); } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct LocationChangedEventArgs + public partial class LocationChangedEventArgs : System.EventArgs { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { throw null; } + 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 enum NavLinkMatch + public partial class Router : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, System.IDisposable { - Prefix = 0, - All = 1, + public Router() { } + [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 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 { } } + [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; } + protected virtual void Render(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, System.Type handler, System.Collections.Generic.IDictionary parameters) { } + public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } } } diff --git a/src/Components/Components/src/Auth/AuthorizeView.cs b/src/Components/Components/src/Auth/AuthorizeView.cs index f1a65b0804..14e4408f73 100644 --- a/src/Components/Components/src/Auth/AuthorizeView.cs +++ b/src/Components/Components/src/Auth/AuthorizeView.cs @@ -23,12 +23,12 @@ namespace Microsoft.AspNetCore.Components /// /// The policy name that determines whether the content can be displayed. /// - [Parameter] public string Policy { get; private set; } + [Parameter] public string Policy { get; set; } /// /// A comma delimited list of roles that are allowed to display the content. /// - [Parameter] public string Roles { get; private set; } + [Parameter] public string Roles { get; set; } /// /// Gets the data used for authorization. diff --git a/src/Components/Components/src/Auth/AuthorizeViewCore.cs b/src/Components/Components/src/Auth/AuthorizeViewCore.cs index 4b1f2f581f..8c60078184 100644 --- a/src/Components/Components/src/Auth/AuthorizeViewCore.cs +++ b/src/Components/Components/src/Auth/AuthorizeViewCore.cs @@ -20,28 +20,28 @@ namespace Microsoft.AspNetCore.Components /// /// The content that will be displayed if the user is authorized. /// - [Parameter] public RenderFragment ChildContent { get; private set; } + [Parameter] public RenderFragment ChildContent { get; set; } /// /// The content that will be displayed if the user is not authorized. /// - [Parameter] public RenderFragment NotAuthorized { get; private set; } + [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; private set; } + [Parameter] public RenderFragment Authorized { get; set; } /// /// The content that will be displayed while asynchronous authorization is in progress. /// - [Parameter] public RenderFragment Authorizing { get; private set; } + [Parameter] public RenderFragment Authorizing { get; set; } /// /// The resource to which access is being controlled. /// - [Parameter] public object Resource { get; private set; } + [Parameter] public object Resource { get; set; } [CascadingParameter] private Task AuthenticationState { get; set; } @@ -58,8 +58,8 @@ namespace Microsoft.AspNetCore.Components } else if (isAuthorized) { - var authorizedContent = Authorized ?? ChildContent; - builder.AddContent(1, authorizedContent?.Invoke(currentAuthenticationState)); + var authorized = Authorized ?? ChildContent; + builder.AddContent(1, authorized?.Invoke(currentAuthenticationState)); } else { diff --git a/src/Components/Components/src/Auth/CascadingAuthenticationState.razor b/src/Components/Components/src/Auth/CascadingAuthenticationState.razor index 5bf4d37b3a..4f2e2bd630 100644 --- a/src/Components/Components/src/Auth/CascadingAuthenticationState.razor +++ b/src/Components/Components/src/Auth/CascadingAuthenticationState.razor @@ -10,7 +10,7 @@ /// /// The content to which the authentication state should be provided. /// - [Parameter] public RenderFragment ChildContent { get; private set; } + [Parameter] public RenderFragment ChildContent { get; set; } protected override void OnInitialized() { diff --git a/src/Components/Components/src/Auth/IHostEnvironmentAuthenticationStateProvider.cs b/src/Components/Components/src/Auth/IHostEnvironmentAuthenticationStateProvider.cs new file mode 100644 index 0000000000..77e8d022d4 --- /dev/null +++ b/src/Components/Components/src/Auth/IHostEnvironmentAuthenticationStateProvider.cs @@ -0,0 +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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Components +{ + /// + /// 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/Components/src/BindMethods.cs b/src/Components/Components/src/BindMethods.cs deleted file mode 100644 index 702b0c74b2..0000000000 --- a/src/Components/Components/src/BindMethods.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.Globalization; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Methods used internally by @bind syntax. Not intended to be used directly. - /// - public static class BindMethods - { - /// - /// Not intended to be used directly. - /// - public static T GetValue(T value) => value; - - /// - /// Not intended to be used directly. - /// - public static string GetValue(DateTime value, string format) => - value == default ? null - : (format == null ? value.ToString() : value.ToString(format)); - - /// - /// Not intended to be used directly. - /// - public static string GetValue(DateTime? value, string format) => - value == default ? null - : (format == null ? value.ToString() : value.Value.ToString(format)); - - /// - /// Not intended to be used directly. - /// - public static string GetValue(DateTimeOffset value, string format) => - value == default ? null - : (format == null ? value.ToString() : value.ToString(format)); - - /// - /// Not intended to be used directly. - /// - public static string GetValue(DateTimeOffset? value, string format) => - value == default ? null - : (format == null ? value.ToString() : value.Value.ToString(format)); - } -} diff --git a/src/Components/Components/src/CascadingParameterState.cs b/src/Components/Components/src/CascadingParameterState.cs index 453fb9692d..8c3e445a86 100644 --- a/src/Components/Components/src/CascadingParameterState.cs +++ b/src/Components/Components/src/CascadingParameterState.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.Components.Reflection; using Microsoft.AspNetCore.Components.Rendering; using System; using System.Collections.Concurrent; @@ -89,7 +90,7 @@ namespace Microsoft.AspNetCore.Components private static ReflectedCascadingParameterInfo[] CreateReflectedCascadingParameterInfos(Type componentType) { List result = null; - var candidateProps = ParameterCollectionExtensions.GetCandidateBindableProperties(componentType); + var candidateProps = ComponentProperties.GetCandidateBindableProperties(componentType); foreach (var prop in candidateProps) { var attribute = prop.GetCustomAttribute(); diff --git a/src/Components/Components/src/CascadingValue.cs b/src/Components/Components/src/CascadingValue.cs index 0547d2d38f..1a03c2557e 100644 --- a/src/Components/Components/src/CascadingValue.cs +++ b/src/Components/Components/src/CascadingValue.cs @@ -21,12 +21,12 @@ namespace Microsoft.AspNetCore.Components /// /// The content to which the value should be provided. /// - [Parameter] public RenderFragment ChildContent { get; private set; } + [Parameter] public RenderFragment ChildContent { get; set; } /// /// The value to be provided. /// - [Parameter] public T Value { get; private set; } + [Parameter] public T Value { get; set; } /// /// Optionally gives a name to the provided value. Descendant components @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Components /// 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; private set; } + [Parameter] public string Name { get; set; } /// /// If true, indicates that will not change. This is a @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Components /// change notifications. Set this flag only if you will not change /// during the component's lifetime. /// - [Parameter] public bool IsFixed { get; private set; } + [Parameter] public bool IsFixed { get; set; } object ICascadingValueComponent.CurrentValue => Value; @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components } /// - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { // Implementing the parameter binding manually, instead of just calling // parameters.SetParameterProperties(this), is just a very slight perf optimization @@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Components // because it serves no useful purpose to have a otherwise. if (!hasSuppliedValue) { - throw new ArgumentException($"Missing required parameter '{nameof(Value)}' for component '{nameof(Parameter)}'."); + throw new ArgumentException($"Missing required parameter '{nameof(Value)}' for component '{GetType().Name}'."); } // Rendering is most efficient when things are queued from rootmost to leafmost. diff --git a/src/Components/Components/src/ChangeEventArgs.cs b/src/Components/Components/src/ChangeEventArgs.cs new file mode 100644 index 0000000000..e64e4c10c7 --- /dev/null +++ b/src/Components/Components/src/ChangeEventArgs.cs @@ -0,0 +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; + +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 index 87ff64cd91..5d3469e622 100644 --- a/src/Components/Components/src/CompilerServices/RuntimeHelpers.cs +++ b/src/Components/Components/src/CompilerServices/RuntimeHelpers.cs @@ -1,5 +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.Threading.Tasks; namespace Microsoft.AspNetCore.Components.CompilerServices { @@ -16,5 +18,39 @@ namespace Microsoft.AspNetCore.Components.CompilerServices /// /// 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 index 23dd8734e7..baa91fd458 100644 --- a/src/Components/Components/src/ComponentBase.cs +++ b/src/Components/Components/src/ComponentBase.cs @@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Components /// Method invoked to apply initial or updated parameters to the component. /// /// The parameters to apply. - public virtual Task SetParametersAsync(ParameterCollection parameters) + public virtual Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); if (!_initialized) diff --git a/src/Components/Components/src/ElementRef.cs b/src/Components/Components/src/ElementRef.cs deleted file mode 100644 index 3bd600bd88..0000000000 --- a/src/Components/Components/src/ElementRef.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.ComponentModel; -using System.Threading; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Represents a reference to a rendered element. - /// - public readonly struct ElementRef - { - 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. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public string __internalId { get; } - - internal string Id => __internalId; - - private ElementRef(string id) - { - __internalId = id; - } - - internal static ElementRef CreateWithUniqueId() - => new ElementRef(CreateUniqueId()); - - 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(); - } - 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"); - } - } - } -} diff --git a/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs b/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs index a007c47f09..99eac1965a 100644 --- a/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs +++ b/src/Components/Components/src/EventCallbackFactoryBinderExtensions.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -126,7 +126,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -164,7 +164,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -240,7 +240,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -259,7 +259,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -278,7 +278,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -298,7 +298,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -318,7 +318,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -358,7 +358,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -378,7 +378,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -398,7 +398,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -418,7 +418,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -439,7 +439,7 @@ namespace Microsoft.AspNetCore.Components /// /// /// - public static EventCallback CreateBinder( + public static EventCallback CreateBinder( this EventCallbackFactory factory, object receiver, Action setter, @@ -449,14 +449,14 @@ namespace Microsoft.AspNetCore.Components return CreateBinderCore(factory, receiver, setter, culture, ParserDelegateCache.Get()); } - private static EventCallback CreateBinderCore( + private static EventCallback CreateBinderCore( this EventCallbackFactory factory, object receiver, Action setter, CultureInfo culture, BindConverter.BindParser converter) { - Action callback = e => + Action callback = e => { T value = default; var converted = false; @@ -489,10 +489,10 @@ namespace Microsoft.AspNetCore.Components setter(default); } }; - return factory.Create(receiver, callback); + return factory.Create(receiver, callback); } - private static EventCallback CreateBinderCore( + private static EventCallback CreateBinderCore( this EventCallbackFactory factory, object receiver, Action setter, @@ -500,7 +500,7 @@ namespace Microsoft.AspNetCore.Components string format, BindConverter.BindParserWithFormat converter) { - Action callback = e => + Action callback = e => { T value = default; var converted = false; @@ -533,7 +533,7 @@ namespace Microsoft.AspNetCore.Components setter(default); } }; - return factory.Create(receiver, callback); + return factory.Create(receiver, callback); } } } diff --git a/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs b/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs new file mode 100644 index 0000000000..d0c4aec303 --- /dev/null +++ b/src/Components/Components/src/EventCallbackFactoryEventArgsExtensions.cs @@ -0,0 +1,86 @@ +// Copyright (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/Forms/DataAnnotationsValidator.cs b/src/Components/Components/src/Forms/DataAnnotationsValidator.cs index 4e76eac07c..63696d2c79 100644 --- a/src/Components/Components/src/Forms/DataAnnotationsValidator.cs +++ b/src/Components/Components/src/Forms/DataAnnotationsValidator.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Components.Forms { throw new InvalidOperationException($"{nameof(DataAnnotationsValidator)} requires a cascading " + $"parameter of type {nameof(EditContext)}. For example, you can use {nameof(DataAnnotationsValidator)} " + - $"inside an {nameof(EditForm)}."); + $"inside an EditForm."); } CurrentEditContext.AddDataAnnotationsValidation(); diff --git a/src/Components/Components/src/Forms/EditContext.cs b/src/Components/Components/src/Forms/EditContext.cs index fd09a241f4..caaf677c37 100644 --- a/src/Components/Components/src/Forms/EditContext.cs +++ b/src/Components/Components/src/Forms/EditContext.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; namespace Microsoft.AspNetCore.Components.Forms { @@ -158,6 +159,16 @@ namespace Microsoft.AspNetCore.Components.Forms } } + /// + /// 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. /// @@ -167,6 +178,14 @@ namespace Microsoft.AspNetCore.Components.Forms ? 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 . /// diff --git a/src/Components/Components/src/Forms/EditContextDataAnnotationsExtensions.cs b/src/Components/Components/src/Forms/EditContextDataAnnotationsExtensions.cs index 6542114a8d..9fce473a41 100644 --- a/src/Components/Components/src/Forms/EditContextDataAnnotationsExtensions.cs +++ b/src/Components/Components/src/Forms/EditContextDataAnnotationsExtensions.cs @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Components.Forms Validator.TryValidateProperty(propertyValue, validationContext, results); messages.Clear(fieldIdentifier); - messages.AddRange(fieldIdentifier, results.Select(result => result.ErrorMessage)); + 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 diff --git a/src/Components/Components/src/Forms/EditContextExpressionExtensions.cs b/src/Components/Components/src/Forms/EditContextExpressionExtensions.cs deleted file mode 100644 index 3d856e241f..0000000000 --- a/src/Components/Components/src/Forms/EditContextExpressionExtensions.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. - -using System; -using System.Collections.Generic; -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Provides extension methods to simplify using with expressions. - /// - public static class EditContextExpressionExtensions - { - /// - /// 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. - /// - /// The . - /// Identifies the field whose current validation messages should be returned. - /// The current validation messages for the specified field. - public static IEnumerable GetValidationMessages(this EditContext editContext, Expression> accessor) - => editContext.GetValidationMessages(FieldIdentifier.Create(accessor)); - - /// - /// Determines whether the specified fields in this has been modified. - /// - /// The . - /// Identifies the field whose current validation messages should be returned. - /// True if the field has been modified; otherwise false. - public static bool IsModified(this EditContext editContext, Expression> accessor) - => editContext.IsModified(FieldIdentifier.Create(accessor)); - } -} diff --git a/src/Components/Components/src/Forms/FieldChangedEventArgs.cs b/src/Components/Components/src/Forms/FieldChangedEventArgs.cs index 9bf18dd486..780a91a01d 100644 --- a/src/Components/Components/src/Forms/FieldChangedEventArgs.cs +++ b/src/Components/Components/src/Forms/FieldChangedEventArgs.cs @@ -1,21 +1,27 @@ // Copyright (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 + 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; } - - internal FieldChangedEventArgs(in FieldIdentifier fieldIdentifier) - { - FieldIdentifier = fieldIdentifier; - } } } diff --git a/src/Components/Components/src/Forms/FieldIdentifier.cs b/src/Components/Components/src/Forms/FieldIdentifier.cs index a113cccbe7..fa3fb72dad 100644 --- a/src/Components/Components/src/Forms/FieldIdentifier.cs +++ b/src/Components/Components/src/Forms/FieldIdentifier.cs @@ -10,7 +10,7 @@ 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 + public readonly struct FieldIdentifier : IEquatable { /// /// Initializes a new instance of the structure. @@ -68,8 +68,15 @@ namespace Microsoft.AspNetCore.Components.Forms /// public override bool Equals(object obj) => obj is FieldIdentifier otherIdentifier - && otherIdentifier.Model == Model - && string.Equals(otherIdentifier.FieldName, FieldName, StringComparison.Ordinal); + && 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) { diff --git a/src/Components/Components/src/Forms/ValidationMessageStore.cs b/src/Components/Components/src/Forms/ValidationMessageStore.cs index 2b520d68df..a8b0664bec 100644 --- a/src/Components/Components/src/Forms/ValidationMessageStore.cs +++ b/src/Components/Components/src/Forms/ValidationMessageStore.cs @@ -33,14 +33,30 @@ namespace Microsoft.AspNetCore.Components.Forms 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 AddRange(in FieldIdentifier fieldIdentifier, IEnumerable messages) + 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. /// @@ -74,6 +90,13 @@ namespace Microsoft.AspNetCore.Components.Forms _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. /// diff --git a/src/Components/Components/src/Forms/ValidationMessageStoreExpressionExtensions.cs b/src/Components/Components/src/Forms/ValidationMessageStoreExpressionExtensions.cs deleted file mode 100644 index 6304c6e2c3..0000000000 --- a/src/Components/Components/src/Forms/ValidationMessageStoreExpressionExtensions.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.Generic; -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.Components.Forms -{ - /// - /// Provides extension methods to simplify using with expressions. - /// - public static class ValidationMessageStoreExpressionExtensions - { - /// - /// Adds a validation message for the specified field. - /// - /// The . - /// Identifies the field for which to add the message. - /// The validation message. - public static void Add(this ValidationMessageStore store, Expression> accessor, string message) - => store.Add(FieldIdentifier.Create(accessor), message); - - /// - /// Adds the messages from the specified collection for the specified field. - /// - /// The . - /// Identifies the field for which to add the messages. - /// The validation messages to be added. - public static void AddRange(this ValidationMessageStore store, Expression> accessor, IEnumerable messages) - => store.AddRange(FieldIdentifier.Create(accessor), messages); - - /// - /// Removes all messages within this for the specified field. - /// - /// The . - /// Identifies the field for which to remove the messages. - public static void Clear(this ValidationMessageStore store, Expression> accessor) - => store.Clear(FieldIdentifier.Create(accessor)); - } -} diff --git a/src/Components/Components/src/Forms/ValidationRequestedEventArgs.cs b/src/Components/Components/src/Forms/ValidationRequestedEventArgs.cs index cd7f0db2b6..52efde8de5 100644 --- a/src/Components/Components/src/Forms/ValidationRequestedEventArgs.cs +++ b/src/Components/Components/src/Forms/ValidationRequestedEventArgs.cs @@ -1,16 +1,24 @@ // Copyright (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 + public sealed class ValidationRequestedEventArgs : EventArgs { - internal static readonly ValidationRequestedEventArgs Empty = new ValidationRequestedEventArgs(); + /// + /// Gets a shared empty instance of . + /// + public static new readonly ValidationRequestedEventArgs Empty = new ValidationRequestedEventArgs(); - internal ValidationRequestedEventArgs() + /// + /// Creates a new instance of . + /// + public ValidationRequestedEventArgs() { } } diff --git a/src/Components/Components/src/Forms/ValidationStateChangedEventArgs.cs b/src/Components/Components/src/Forms/ValidationStateChangedEventArgs.cs index 0ac4af6658..fd8dbb8d69 100644 --- a/src/Components/Components/src/Forms/ValidationStateChangedEventArgs.cs +++ b/src/Components/Components/src/Forms/ValidationStateChangedEventArgs.cs @@ -1,16 +1,24 @@ // Copyright (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 + public sealed class ValidationStateChangedEventArgs : EventArgs { - internal static readonly ValidationStateChangedEventArgs Empty = new ValidationStateChangedEventArgs(); + /// + /// Gets a shared empty instance of . + /// + public new static readonly ValidationStateChangedEventArgs Empty = new ValidationStateChangedEventArgs(); - internal ValidationStateChangedEventArgs() + /// + /// Creates a new instance of + /// + public ValidationStateChangedEventArgs() { } } diff --git a/src/Components/Components/src/IComponent.cs b/src/Components/Components/src/IComponent.cs index c06dbb193e..ec1059b1e6 100644 --- a/src/Components/Components/src/IComponent.cs +++ b/src/Components/Components/src/IComponent.cs @@ -21,6 +21,6 @@ namespace Microsoft.AspNetCore.Components /// /// The parameters. /// A that completes when the component has finished updating and rendering itself. - Task SetParametersAsync(ParameterCollection parameters); + Task SetParametersAsync(ParameterView parameters); } } diff --git a/src/Components/Components/src/IUriHelper.cs b/src/Components/Components/src/IUriHelper.cs deleted file mode 100644 index 6c4756f2d2..0000000000 --- a/src/Components/Components/src/IUriHelper.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; -using Microsoft.AspNetCore.Components.Routing; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Helpers for working with URIs and navigation state. - /// - public interface IUriHelper - { - /// - /// Gets the current absolute URI. - /// - /// The current absolute URI. - string GetAbsoluteUri(); - - /// - /// An event that fires when the navigation location has changed. - /// - event EventHandler OnLocationChanged; - - /// - /// Converts a relative URI into an absolute one (by resolving it - /// relative to the current absolute URI). - /// - /// The relative URI. - /// The absolute URI. - Uri ToAbsoluteUri(string href); - - /// - /// Gets the base URI (with trailing slash) that can be prepended before relative URI paths to produce an absolute URI. - /// Typically this corresponds to the 'href' attribute on the document's <base> element. - /// - /// The URI prefix, which has a trailing slash. - string GetBaseUri(); - - /// - /// Given a base URI (e.g., one previously returned by ), - /// converts an absolute URI into one relative to the base URI prefix. - /// - /// The base URI prefix (e.g., previously returned by ). - /// An absolute URI that is within the space of the base URI. - /// A relative URI path. - string ToBaseRelativePath(string baseUri, string locationAbsolute); - - /// - /// Navigates to the specified URI. - /// - /// The destination URI. This can be absolute, or relative to the base URI - /// (as returned by ). - void NavigateTo(string uri); - - /// - /// 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. - void NavigateTo(string uri, bool forceLoad); - } -} diff --git a/src/Components/Components/src/LayoutComponentBase.cs b/src/Components/Components/src/LayoutComponentBase.cs index 2480cd2e18..776b97b280 100644 --- a/src/Components/Components/src/LayoutComponentBase.cs +++ b/src/Components/Components/src/LayoutComponentBase.cs @@ -16,6 +16,6 @@ namespace Microsoft.AspNetCore.Components /// Gets the content to be rendered inside the layout. /// [Parameter] - public RenderFragment Body { get; private set; } + public RenderFragment Body { get; set; } } } diff --git a/src/Components/Components/src/LocationChangeException.cs b/src/Components/Components/src/LocationChangeException.cs new file mode 100644 index 0000000000..13010eb5c1 --- /dev/null +++ b/src/Components/Components/src/LocationChangeException.cs @@ -0,0 +1,23 @@ +// Copyright (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/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj index 6c773e9d42..dffcf43a97 100644 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj +++ b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Components/Components/src/NavigationException.cs b/src/Components/Components/src/NavigationException.cs index 2693ce39b0..5acb891e6f 100644 --- a/src/Components/Components/src/NavigationException.cs +++ b/src/Components/Components/src/NavigationException.cs @@ -6,7 +6,7 @@ using System; namespace Microsoft.AspNetCore.Components { /// - /// Exception thrown when an is not able to navigate to a different url. + /// Exception thrown when an is not able to navigate to a different url. /// public class NavigationException : Exception { diff --git a/src/Components/Components/src/NavigationManager.cs b/src/Components/Components/src/NavigationManager.cs new file mode 100644 index 0000000000..d75077026f --- /dev/null +++ b/src/Components/Components/src/NavigationManager.cs @@ -0,0 +1,269 @@ +// Copyright (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 new file mode 100644 index 0000000000..d5bcecb1f7 --- /dev/null +++ b/src/Components/Components/src/OwningComponentBase.cs @@ -0,0 +1,100 @@ +// Copyright (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/PageDisplay.cs b/src/Components/Components/src/PageDisplay.cs index 37e429915b..14df824d13 100644 --- a/src/Components/Components/src/PageDisplay.cs +++ b/src/Components/Components/src/PageDisplay.cs @@ -24,25 +24,25 @@ namespace Microsoft.AspNetCore.Components /// The type must implement . /// [Parameter] - public Type Page { get; private set; } + public Type Page { get; set; } /// /// Gets or sets the parameters to pass to the page. /// [Parameter] - public IDictionary PageParameters { get; private set; } + public IDictionary PageParameters { get; set; } /// /// The content that will be displayed if the user is not authorized. /// [Parameter] - public RenderFragment NotAuthorizedContent { get; private set; } + public RenderFragment NotAuthorized { get; set; } /// /// The content that will be displayed while asynchronous authorization is in progress. /// [Parameter] - public RenderFragment AuthorizingContent { get; private set; } + public RenderFragment Authorizing { get; set; } /// public void Attach(RenderHandle renderHandle) @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Components } /// - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); Render(); @@ -109,14 +109,14 @@ namespace Microsoft.AspNetCore.Components } // Some authorization data exists, so we do need to wrap the fragment - RenderFragment authorizedContent = context => pageFragment; + RenderFragment authorized = context => pageFragment; return builder => { builder.OpenComponent(0); builder.AddAttribute(1, nameof(AuthorizeViewWithSuppliedData.AuthorizeDataParam), authorizeData); - builder.AddAttribute(2, nameof(AuthorizeViewWithSuppliedData.Authorized), authorizedContent); - builder.AddAttribute(3, nameof(AuthorizeViewWithSuppliedData.NotAuthorized), NotAuthorizedContent ?? DefaultNotAuthorizedContent); - builder.AddAttribute(4, nameof(AuthorizeViewWithSuppliedData.Authorizing), AuthorizingContent); + builder.AddAttribute(2, nameof(AuthorizeViewWithSuppliedData.Authorized), authorized); + builder.AddAttribute(3, nameof(AuthorizeViewWithSuppliedData.NotAuthorized), NotAuthorized ?? DefaultNotAuthorized); + builder.AddAttribute(4, nameof(AuthorizeViewWithSuppliedData.Authorizing), Authorizing); builder.CloseComponent(); }; } @@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Components // There has to be some default content. If we render blank by default, developers // will find it hard to guess why their UI isn't appearing. - private static RenderFragment DefaultNotAuthorizedContent(AuthenticationState authenticationState) + private static RenderFragment DefaultNotAuthorized(AuthenticationState authenticationState) => builder => builder.AddContent(0, "Not authorized"); } } diff --git a/src/Components/Components/src/ParameterEnumerator.cs b/src/Components/Components/src/ParameterEnumerator.cs deleted file mode 100644 index 6abc92e8a1..0000000000 --- a/src/Components/Components/src/ParameterEnumerator.cs +++ /dev/null @@ -1,137 +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; -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// An enumerator that iterates through a . - /// - public struct ParameterEnumerator - { - private RenderTreeFrameParameterEnumerator _directParamsEnumerator; - private CascadingParameterEnumerator _cascadingParameterEnumerator; - private bool _isEnumeratingDirectParams; - - internal ParameterEnumerator(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 Parameter 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(); - } - - struct RenderTreeFrameParameterEnumerator - { - private readonly RenderTreeFrame[] _frames; - private readonly int _ownerIndex; - private readonly int _ownerDescendantsEndIndexExcl; - private int _currentIndex; - private Parameter _current; - - internal RenderTreeFrameParameterEnumerator(RenderTreeFrame[] frames, int ownerIndex) - { - _frames = frames; - _ownerIndex = ownerIndex; - _ownerDescendantsEndIndexExcl = ownerIndex + _frames[ownerIndex].ElementSubtreeLength; - _currentIndex = ownerIndex; - _current = default; - } - - public Parameter 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 Parameter(frame.AttributeName, frame.AttributeValue, false); - - return true; - } - } - - struct CascadingParameterEnumerator - { - private readonly IReadOnlyList _cascadingParameters; - private int _currentIndex; - private Parameter _current; - - public CascadingParameterEnumerator(IReadOnlyList cascadingParameters) - { - _cascadingParameters = cascadingParameters; - _currentIndex = -1; - _current = default; - } - - public Parameter 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 Parameter(state.LocalValueName, state.ValueSupplier.CurrentValue, true); - return true; - } - else - { - return false; - } - } - } - } -} diff --git a/src/Components/Components/src/Parameter.cs b/src/Components/Components/src/ParameterValue.cs similarity index 89% rename from src/Components/Components/src/Parameter.cs rename to src/Components/Components/src/ParameterValue.cs index 3ba8cdff2f..c080880de2 100644 --- a/src/Components/Components/src/Parameter.cs +++ b/src/Components/Components/src/ParameterValue.cs @@ -7,8 +7,15 @@ namespace Microsoft.AspNetCore.Components /// Represents a single parameter supplied to an /// by its parent in the render tree. /// - public readonly struct Parameter + public readonly struct ParameterValue { + internal ParameterValue(string name, object value, bool cascading) + { + Name = name; + Value = value; + Cascading = cascading; + } + /// /// Gets the name of the parameter. /// @@ -24,12 +31,5 @@ namespace Microsoft.AspNetCore.Components /// was supplied by a . /// public bool Cascading { get; } - - internal Parameter(string name, object value, bool cascading) - { - Name = name; - Value = value; - Cascading = cascading; - } } } diff --git a/src/Components/Components/src/ParameterCollection.cs b/src/Components/Components/src/ParameterView.cs similarity index 54% rename from src/Components/Components/src/ParameterCollection.cs rename to src/Components/Components/src/ParameterView.cs index a929c8071e..3d682cc09c 100644 --- a/src/Components/Components/src/ParameterCollection.cs +++ b/src/Components/Components/src/ParameterView.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Components.Reflection; using Microsoft.AspNetCore.Components.RenderTree; namespace Microsoft.AspNetCore.Components @@ -11,27 +12,26 @@ namespace Microsoft.AspNetCore.Components /// Represents a collection of parameters supplied to an /// by its parent in the render tree. /// - public readonly struct ParameterCollection + public readonly struct ParameterView { - private const string GeneratedParameterCollectionElementName = "__ARTIFICIAL_PARAMETER_COLLECTION"; - private static readonly RenderTreeFrame[] _emptyCollectionFrames = new RenderTreeFrame[] + private const string GeneratedParameterViewElementName = "__ARTIFICIAL_PARAMETER_VIEW"; + private static readonly RenderTreeFrame[] _emptyFrames = new RenderTreeFrame[] { RenderTreeFrame.Element(0, string.Empty).WithComponentSubtreeLength(1) }; - private static readonly ParameterCollection _emptyCollection - = new ParameterCollection(_emptyCollectionFrames, 0, null); + private static readonly ParameterView _empty = new ParameterView(_emptyFrames, 0, null); private readonly RenderTreeFrame[] _frames; private readonly int _ownerIndex; private readonly IReadOnlyList _cascadingParametersOrNull; - internal ParameterCollection(RenderTreeFrame[] frames, int ownerIndex) + internal ParameterView(RenderTreeFrame[] frames, int ownerIndex) : this(frames, ownerIndex, null) { } - private ParameterCollection(RenderTreeFrame[] frames, int ownerIndex, IReadOnlyList cascadingParametersOrNull) + private ParameterView(RenderTreeFrame[] frames, int ownerIndex, IReadOnlyList cascadingParametersOrNull) { _frames = frames; _ownerIndex = ownerIndex; @@ -39,16 +39,16 @@ namespace Microsoft.AspNetCore.Components } /// - /// Gets an empty . + /// Gets an empty . /// - public static ParameterCollection Empty => _emptyCollection; + public static ParameterView Empty => _empty; /// - /// Returns an enumerator that iterates through the . + /// Returns an enumerator that iterates through the . /// /// The enumerator. - public ParameterEnumerator GetEnumerator() - => new ParameterEnumerator(_frames, _ownerIndex, _cascadingParametersOrNull); + public Enumerator GetEnumerator() + => new Enumerator(_frames, _ownerIndex, _cascadingParametersOrNull); /// /// Gets the value of the parameter with the specified name. @@ -94,9 +94,9 @@ namespace Microsoft.AspNetCore.Components => TryGetValue(parameterName, out T result) ? result : defaultValue; /// - /// Returns a dictionary populated with the contents of the . + /// Returns a dictionary populated with the contents of the . /// - /// A dictionary populated with the contents of the . + /// A dictionary populated with the contents of the . public IReadOnlyDictionary ToDictionary() { var result = new Dictionary(); @@ -107,13 +107,13 @@ namespace Microsoft.AspNetCore.Components return result; } - internal ParameterCollection WithCascadingParameters(IReadOnlyList cascadingParameters) - => new ParameterCollection(_frames, _ownerIndex, cascadingParameters); + internal ParameterView WithCascadingParameters(IReadOnlyList cascadingParameters) + => new ParameterView(_frames, _ownerIndex, cascadingParameters); // It's internal because there isn't a known use case for user code comparing - // ParameterCollection instances, and even if there was, it's unlikely it should + // 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(ParameterCollection oldParameters) + 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 @@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Components } // We need to prefix the captured frames with an "owner" frame that - // describes the length of the buffer so that ParameterCollection + // 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); @@ -199,14 +199,14 @@ namespace Microsoft.AspNetCore.Components } /// - /// Creates a new from the given . + /// Creates a new from the given . /// /// The with the parameters. - /// A . - public static ParameterCollection FromDictionary(IDictionary parameters) + /// A . + public static ParameterView FromDictionary(IDictionary parameters) { var frames = new RenderTreeFrame[parameters.Count + 1]; - frames[0] = RenderTreeFrame.Element(0, GeneratedParameterCollectionElementName) + frames[0] = RenderTreeFrame.Element(0, GeneratedParameterViewElementName) .WithElementSubtreeLength(frames.Length); var i = 0; @@ -215,7 +215,153 @@ namespace Microsoft.AspNetCore.Components frames[++i] = RenderTreeFrame.Attribute(i, kvp.Key, kvp.Value); } - return new ParameterCollection(frames, 0); + return new ParameterView(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/ParameterCollectionExtensions.cs b/src/Components/Components/src/Reflection/ComponentProperties.cs similarity index 92% rename from src/Components/Components/src/ParameterCollectionExtensions.cs rename to src/Components/Components/src/Reflection/ComponentProperties.cs index fb23b5de49..5caeab20b1 100644 --- a/src/Components/Components/src/ParameterCollectionExtensions.cs +++ b/src/Components/Components/src/Reflection/ComponentProperties.cs @@ -7,29 +7,17 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; -using Microsoft.AspNetCore.Components.Reflection; -namespace Microsoft.AspNetCore.Components +namespace Microsoft.AspNetCore.Components.Reflection { - /// - /// Extension methods for the type. - /// - public static class ParameterCollectionExtensions + internal static class ComponentProperties { private const BindingFlags _bindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase; private readonly static ConcurrentDictionary _cachedWritersByType = new ConcurrentDictionary(); - /// - /// For each parameter property on , updates its value to - /// match the corresponding entry in the . - /// - /// The . - /// An object that has a public writable property matching each parameter's name and type. - public static void SetParameterProperties( - in this ParameterCollection parameterCollection, - object target) + public static void SetProperties(in ParameterView parameters, object target) { if (target == null) { @@ -47,7 +35,7 @@ namespace Microsoft.AspNetCore.Components if (writers.CaptureUnmatchedValuesWriter == null) { // Logic for components without a CaptureUnmatchedValues parameter - foreach (var parameter in parameterCollection) + foreach (var parameter in parameters) { var parameterName = parameter.Name; if (!writers.WritersByName.TryGetValue(parameterName, out var writer)) @@ -65,7 +53,7 @@ namespace Microsoft.AspNetCore.Components // Logic with components with a CaptureUnmatchedValues parameter var isCaptureUnmatchedValuesParameterSetExplicitly = false; Dictionary unmatched = null; - foreach (var parameter in parameterCollection) + foreach (var parameter in parameters) { var parameterName = parameter.Name; if (string.Equals(parameterName, writers.CaptureUnmatchedValuesPropertyName, StringComparison.OrdinalIgnoreCase)) diff --git a/src/Components/Components/src/Reflection/MemberAssignment.cs b/src/Components/Components/src/Reflection/MemberAssignment.cs index 46d2b80569..0ab288cedc 100644 --- a/src/Components/Components/src/Reflection/MemberAssignment.cs +++ b/src/Components/Components/src/Reflection/MemberAssignment.cs @@ -51,7 +51,16 @@ namespace Microsoft.AspNetCore.Components.Reflection } public void SetValue(object target, object value) - => _setterDelegate((TTarget)target, (TValue)value); + { + if (value == null) + { + _setterDelegate((TTarget)target, default); + } + else + { + _setterDelegate((TTarget)target, (TValue)value); + } + } } } } diff --git a/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs b/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs new file mode 100644 index 0000000000..3fb698d3ee --- /dev/null +++ b/src/Components/Components/src/RenderTree/ArrayBuilderExtensions.cs @@ -0,0 +1,27 @@ +// Copyright (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 +{ + 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/RenderTreeBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs index b0e0687617..c7e2324d36 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components.RenderTree { @@ -17,13 +16,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// /// Provides methods for building a collection of entries. /// - public class RenderTreeBuilder : IDisposable + 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 Renderer _renderer; private readonly ArrayBuilder _entries = new ArrayBuilder(); private readonly Stack _openElementIndices = new Stack(); private RenderTreeFrameType? _lastNonAttributeFrameType; @@ -33,16 +31,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// /// The reserved parameter name used for supplying child content. /// - public const string ChildContent = nameof(ChildContent); - - /// - /// Constructs an instance of . - /// - /// The associated . - public RenderTreeBuilder(Renderer renderer) - { - _renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); - } + private const string ChildContent = nameof(ChildContent); /// /// Appends a frame representing an element, i.e., a container for other frames. @@ -206,40 +195,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree } } - /// - /// - /// Appends a frame representing an -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, Action value) - { - AddAttribute(sequence, name, (MulticastDelegate)value); - } - - /// - /// - /// Appends a frame representing a -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, Func value) - { - AddAttribute(sequence, name, (MulticastDelegate)value); - } - /// /// /// Appends a frame representing a delegate-valued attribute. @@ -587,7 +542,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// /// 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) + public void AddElementReferenceCapture(int sequence, Action elementReferenceCaptureAction) { if (GetCurrentParentFrameType() != RenderTreeFrameType.Element) { @@ -619,17 +574,21 @@ namespace Microsoft.AspNetCore.Components.RenderTree Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue)); } - // Internal for tests - // Not public because there's no current use case for user code defining regions arbitrarily. - // Currently the sole use case for regions is when appending a RenderFragment. - internal void OpenRegion(int sequence) + /// + /// 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) { _openElementIndices.Push(_entries.Count); Append(RenderTreeFrame.Region(sequence)); } - // See above for why this is not public - internal void CloseRegion() + /// + /// 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]; diff --git a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs index 933e1f9ab5..bc6f82df29 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs @@ -99,6 +99,10 @@ namespace Microsoft.AspNetCore.Components.RenderTree 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 @@ -108,11 +112,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree else { // Keys don't match - if (keyedItemInfos == null) - { - keyedItemInfos = BuildKeyToInfoLookup(diffContext, origOldStartIndex, oldEndIndexExcl, origNewStartIndex, newEndIndexExcl); - } - 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; @@ -520,8 +519,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree // 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 ParameterCollection(oldTree, oldComponentIndex); - var newParameters = new ParameterCollection(newTree, newComponentIndex); + var oldParameters = new ParameterView(oldTree, oldComponentIndex); + var newParameters = new ParameterView(newTree, newComponentIndex); if (!newParameters.DefinitelyEquals(oldParameters)) { componentState.SetDirectParameters(newParameters); @@ -894,7 +893,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree var childComponentState = frame.ComponentState; // Set initial parameters - var initialParameters = new ParameterCollection(frames, frameIndex); + var initialParameters = new ParameterView(frames, frameIndex); childComponentState.SetDirectParameters(initialParameters); } @@ -914,9 +913,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) { - var newElementRef = ElementRef.CreateWithUniqueId(); - newFrame = newFrame.WithElementReferenceCaptureId(newElementRef.Id); - newFrame.ElementReferenceCaptureAction(newElementRef); + var newElementReference = ElementReference.CreateWithUniqueId(); + newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id); + newFrame.ElementReferenceCaptureAction(newElementReference); } private static void InitializeNewComponentReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) diff --git a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs b/src/Components/Components/src/RenderTree/RenderTreeFrame.cs index 1c0105ad77..f3e003080b 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeFrame.cs @@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// 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; + [FieldOffset(24)] public readonly Action ElementReferenceCaptureAction; // -------------------------------------------------------------------------------- // RenderTreeFrameType.ComponentReferenceCapture @@ -279,7 +279,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree } // Element reference capture constructor - private RenderTreeFrame(int sequence, Action elementReferenceCaptureAction, string elementReferenceCaptureId) + private RenderTreeFrame(int sequence, Action elementReferenceCaptureAction, string elementReferenceCaptureId) : this() { FrameType = RenderTreeFrameType.ElementReferenceCapture; @@ -319,7 +319,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree internal static RenderTreeFrame Region(int sequence) => new RenderTreeFrame(sequence, regionSubtreeLength: 0); - internal static RenderTreeFrame ElementReferenceCapture(int sequence, Action elementReferenceCaptureAction) + 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) diff --git a/src/Components/Components/src/Rendering/ComponentState.cs b/src/Components/Components/src/Rendering/ComponentState.cs index 1d34ffff84..a0609b9331 100644 --- a/src/Components/Components/src/Rendering/ComponentState.cs +++ b/src/Components/Components/src/Rendering/ComponentState.cs @@ -36,8 +36,8 @@ namespace Microsoft.AspNetCore.Components.Rendering Component = component ?? throw new ArgumentNullException(nameof(component)); _renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); _cascadingParameters = CascadingParameterState.FindCascadingParameters(this); - CurrrentRenderTree = new RenderTreeBuilder(renderer); - _renderTreeBuilderPrevious = new RenderTreeBuilder(renderer); + CurrentRenderTree = new RenderTreeBuilder(); + _renderTreeBuilderPrevious = new RenderTreeBuilder(); if (_cascadingParameters != null) { @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Components.Rendering public int ComponentId { get; } public IComponent Component { get; } public ComponentState ParentComponentState { get; } - public RenderTreeBuilder CurrrentRenderTree { get; private set; } + public RenderTreeBuilder CurrentRenderTree { get; private set; } public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment) { @@ -61,17 +61,17 @@ namespace Microsoft.AspNetCore.Components.Rendering } // Swap the old and new tree builders - (CurrrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrrentRenderTree); + (CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree); - CurrrentRenderTree.Clear(); - renderFragment(CurrrentRenderTree); + CurrentRenderTree.Clear(); + renderFragment(CurrentRenderTree); var diff = RenderTreeDiffBuilder.ComputeDiff( _renderer, batchBuilder, ComponentId, _renderTreeBuilderPrevious.GetFrames(), - CurrrentRenderTree.GetFrames()); + CurrentRenderTree.GetFrames()); batchBuilder.UpdatedComponentDiffs.Append(diff); } @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Components.Rendering disposable.Dispose(); } - RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrrentRenderTree.GetFrames()); + RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrentRenderTree.GetFrames()); if (_hasAnyCascadingParameterSubscriptions) { @@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Components.Rendering return Task.CompletedTask; } - public void SetDirectParameters(ParameterCollection parameters) + public void SetDirectParameters(ParameterView parameters) { // Note: We should be careful to ensure that the framework never calls // IComponent.SetParameters directly elsewhere. We should only call it @@ -137,8 +137,8 @@ namespace Microsoft.AspNetCore.Components.Rendering public void NotifyCascadingValueChanged() { var directParams = _latestDirectParametersSnapshot != null - ? new ParameterCollection(_latestDirectParametersSnapshot.Buffer, 0) - : ParameterCollection.Empty; + ? new ParameterView(_latestDirectParametersSnapshot.Buffer, 0) + : ParameterView.Empty; var allParams = directParams.WithCascadingParameters(_cascadingParameters); var task = Component.SetParametersAsync(allParams); _renderer.AddToPendingTasks(task); @@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Components.Rendering private void DisposeBuffers() { ((IDisposable)_renderTreeBuilderPrevious).Dispose(); - ((IDisposable)CurrrentRenderTree).Dispose(); + ((IDisposable)CurrentRenderTree).Dispose(); _latestDirectParametersSnapshot?.Dispose(); } } diff --git a/src/Components/Components/src/Rendering/HtmlRenderer.cs b/src/Components/Components/src/Rendering/HtmlRenderer.cs index 13015c0ffe..5eb2e71095 100644 --- a/src/Components/Components/src/Rendering/HtmlRenderer.cs +++ b/src/Components/Components/src/Rendering/HtmlRenderer.cs @@ -4,8 +4,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.Extensions.Logging; @@ -22,6 +22,8 @@ namespace Microsoft.AspNetCore.Components.Rendering "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr" }; + private static readonly Task CanceledRenderTask = Task.FromCanceled(new CancellationToken(canceled: true)); + private readonly Func _htmlEncoder; /// @@ -41,7 +43,19 @@ namespace Microsoft.AspNetCore.Components.Rendering /// protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) { - return Task.CompletedTask; + // By default we return a canceled task. This has the effect of making it so that the + // OnAfterRenderAsync callbacks on components don't run by default. + // This way, by default prerendering gets the correct behavior and other renderers + // override the UpdateDisplayAsync method already, so those components can + // either complete a task when the client acknowledges the render, or return a canceled task + // when the renderer gets disposed. + + // We believe that returning a canceled task is the right behavior as we expect that any class + // that subclasses this class to provide an implementation for a given rendering scenario respects + // the contract that OnAfterRender should only be called when the display has successfully been updated + // and the application is interactive. (Element and component references are populated and JavaScript interop + // is available). + return CanceledRenderTask; } /// @@ -49,9 +63,9 @@ namespace Microsoft.AspNetCore.Components.Rendering /// of the HTML produced by the component. /// /// The type of the . - /// A with the initial parameters to render the component. + /// A with the initial parameters to render the component. /// A that on completion returns a sequence of fragments that represent the HTML text of the component. - public async Task RenderComponentAsync(Type componentType, ParameterCollection initialParameters) + public async Task RenderComponentAsync(Type componentType, ParameterView initialParameters) { var (componentId, frames) = await CreateInitialRenderAsync(componentType, initialParameters); @@ -66,9 +80,9 @@ namespace Microsoft.AspNetCore.Components.Rendering /// of the HTML produced by the component. /// /// The type of the . - /// A with the initial parameters to render the component. + /// A with the initial parameters to render the component. /// A that on completion returns a sequence of fragments that represent the HTML text of the component. - public Task RenderComponentAsync(ParameterCollection initialParameters) where TComponent : IComponent + public Task RenderComponentAsync(ParameterView initialParameters) where TComponent : IComponent { return RenderComponentAsync(typeof(TComponent), initialParameters); } @@ -224,7 +238,7 @@ namespace Microsoft.AspNetCore.Components.Rendering return position + maxElements; } - private async Task<(int, ArrayRange)> CreateInitialRenderAsync(Type componentType, ParameterCollection initialParameters) + private async Task<(int, ArrayRange)> CreateInitialRenderAsync(Type componentType, ParameterView initialParameters) { var component = InstantiateComponent(componentType); var componentId = AssignRootComponentId(component); diff --git a/src/Components/Components/src/Rendering/Renderer.Log.cs b/src/Components/Components/src/Rendering/Renderer.Log.cs index 68a28b62a1..3b70f58973 100644 --- a/src/Components/Components/src/Rendering/Renderer.Log.cs +++ b/src/Components/Components/src/Rendering/Renderer.Log.cs @@ -56,9 +56,9 @@ namespace Microsoft.AspNetCore.Components.Rendering } } - internal static void HandlingEvent(ILogger logger, ulong eventHandlerId, UIEventArgs eventArgs) + internal static void HandlingEvent(ILogger logger, ulong eventHandlerId, EventArgs eventArgs) { - _handlingEvent(logger, eventHandlerId, eventArgs?.Type ?? "null", null); + _handlingEvent(logger, eventHandlerId, eventArgs?.GetType().Name ?? "null", null); } } } diff --git a/src/Components/Components/src/Rendering/Renderer.cs b/src/Components/Components/src/Rendering/Renderer.cs index 60fe23e423..6e0ed1633e 100644 --- a/src/Components/Components/src/Rendering/Renderer.cs +++ b/src/Components/Components/src/Rendering/Renderer.cs @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Components.Rendering /// /// The id for the component. /// The representing the current render tree. - private protected ArrayRange GetCurrentRenderTreeFrames(int componentId) => GetRequiredComponentState(componentId).CurrrentRenderTree.GetFrames(); + private protected ArrayRange GetCurrentRenderTreeFrames(int componentId) => GetRequiredComponentState(componentId).CurrentRenderTree.GetFrames(); /// /// Performs the first render for a root component, waiting for this component and all @@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Components.Rendering /// protected Task RenderRootComponentAsync(int componentId) { - return RenderRootComponentAsync(componentId, ParameterCollection.Empty); + return RenderRootComponentAsync(componentId, ParameterView.Empty); } /// @@ -120,12 +120,12 @@ namespace Microsoft.AspNetCore.Components.Rendering /// this more than once. /// /// The ID returned by . - /// The with the initial parameters to use for rendering. + /// 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, ParameterCollection initialParameters) + protected async Task RenderRootComponentAsync(int componentId, ParameterView initialParameters) { if (Interlocked.CompareExchange(ref _pendingTasks, new List(), null) != null) { @@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Components.Rendering /// A which will complete once all asynchronous processing related to the event /// has completed. /// - public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, UIEventArgs eventArgs) + public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs) { EnsureSynchronizationContext(); @@ -235,6 +235,7 @@ namespace Microsoft.AspNetCore.Components.Rendering catch (Exception e) { HandleException(e); + return Task.CompletedTask; } finally { @@ -444,8 +445,12 @@ namespace Microsoft.AspNetCore.Components.Rendering { if (updateDisplayTask.IsCanceled) { - // The display update was cancelled (maybe due to a timeout on the components server-side case or due - // to the renderer being disposed) + // 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) @@ -643,7 +648,7 @@ namespace Microsoft.AspNetCore.Components.Rendering if (componentState != null) { RenderTreeUpdater.UpdateToMatchClientState( - componentState.CurrrentRenderTree, + componentState.CurrentRenderTree, eventHandlerId, fieldInfo.FieldValue); } diff --git a/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs b/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs new file mode 100644 index 0000000000..89dac06e0f --- /dev/null +++ b/src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs @@ -0,0 +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. + +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/LocationChangedEventArgs.cs b/src/Components/Components/src/Routing/LocationChangedEventArgs.cs index 1b3ab4cc64..7d1dca39e4 100644 --- a/src/Components/Components/src/Routing/LocationChangedEventArgs.cs +++ b/src/Components/Components/src/Routing/LocationChangedEventArgs.cs @@ -6,9 +6,9 @@ using System; namespace Microsoft.AspNetCore.Components.Routing { /// - /// for . + /// for . /// - public readonly struct LocationChangedEventArgs + public class LocationChangedEventArgs : EventArgs { /// /// Initializes a new instance of . diff --git a/src/Components/Components/src/Routing/RouteEntry.cs b/src/Components/Components/src/Routing/RouteEntry.cs index cff9420bd9..3870ef2245 100644 --- a/src/Components/Components/src/Routing/RouteEntry.cs +++ b/src/Components/Components/src/Routing/RouteEntry.cs @@ -8,14 +8,17 @@ namespace Microsoft.AspNetCore.Components.Routing { internal class RouteEntry { - public RouteEntry(RouteTemplate template, Type handler) + 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) @@ -45,6 +48,18 @@ namespace Microsoft.AspNetCore.Components.Routing } } + // 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/RouteTableFactory.cs b/src/Components/Components/src/Routing/RouteTableFactory.cs index eae29a7530..e0601bc95a 100644 --- a/src/Components/Components/src/Routing/RouteTableFactory.cs +++ b/src/Components/Components/src/Routing/RouteTableFactory.cs @@ -34,19 +34,38 @@ namespace Microsoft.AspNetCore.Components internal static RouteTable Create(IEnumerable componentTypes) { - var routes = new List(); - foreach (var type in 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 = type.GetCustomAttributes(inherit: false); + var routeAttributes = componentType.GetCustomAttributes(inherit: false); - foreach (var routeAttribute in routeAttributes) + 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 template = TemplateParser.ParseTemplate(routeAttribute.Template); - var entry = new RouteEntry(template, type); + var unusedRouteParameterNames = allRouteParameterNames + .Except(GetParameterNames(parsedTemplate), StringComparer.OrdinalIgnoreCase) + .ToArray(); + var entry = new RouteEntry(parsedTemplate, keyValuePair.Key, unusedRouteParameterNames); routes.Add(entry); } } @@ -54,6 +73,14 @@ namespace Microsoft.AspNetCore.Components 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 diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 451de47bc5..96eca17322 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Components.Routing bool _navigationInterceptionEnabled; ILogger _logger; - [Inject] private IUriHelper UriHelper { get; set; } + [Inject] private NavigationManager NavigationManager { get; set; } [Inject] private INavigationInterception NavigationInterception { get; set; } @@ -36,22 +36,22 @@ namespace Microsoft.AspNetCore.Components.Routing /// Gets or sets the assembly that should be searched, along with its referenced /// assemblies, for components matching the URI. /// - [Parameter] public Assembly AppAssembly { get; private set; } + [Parameter] public Assembly AppAssembly { get; set; } /// /// Gets or sets the type of the component that should be used as a fallback when no match is found for the requested route. /// - [Parameter] public RenderFragment NotFoundContent { get; private set; } + [Parameter] public RenderFragment NotFound { get; set; } /// /// The content that will be displayed if the user is not authorized. /// - [Parameter] public RenderFragment NotAuthorizedContent { get; private set; } + [Parameter] public RenderFragment NotAuthorized { get; set; } /// /// The content that will be displayed while asynchronous authorization is in progress. /// - [Parameter] public RenderFragment AuthorizingContent { get; private set; } + [Parameter] public RenderFragment Authorizing { get; set; } private RouteTable Routes { get; set; } @@ -60,13 +60,13 @@ namespace Microsoft.AspNetCore.Components.Routing { _logger = LoggerFactory.CreateLogger(); _renderHandle = renderHandle; - _baseUri = UriHelper.GetBaseUri(); - _locationAbsolute = UriHelper.GetAbsoluteUri(); - UriHelper.OnLocationChanged += OnLocationChanged; + _baseUri = NavigationManager.BaseUri; + _locationAbsolute = NavigationManager.Uri; + NavigationManager.LocationChanged += OnLocationChanged; } /// - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); Routes = RouteTableFactory.Create(AppAssembly); @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Components.Routing /// public void Dispose() { - UriHelper.OnLocationChanged -= OnLocationChanged; + NavigationManager.LocationChanged -= OnLocationChanged; } private string StringUntilAny(string str, char[] chars) @@ -94,14 +94,14 @@ namespace Microsoft.AspNetCore.Components.Routing builder.OpenComponent(0, typeof(PageDisplay)); builder.AddAttribute(1, nameof(PageDisplay.Page), handler); builder.AddAttribute(2, nameof(PageDisplay.PageParameters), parameters); - builder.AddAttribute(3, nameof(PageDisplay.NotAuthorizedContent), NotAuthorizedContent); - builder.AddAttribute(4, nameof(PageDisplay.AuthorizingContent), AuthorizingContent); + builder.AddAttribute(3, nameof(PageDisplay.NotAuthorized), NotAuthorized); + builder.AddAttribute(4, nameof(PageDisplay.Authorizing), Authorizing); builder.CloseComponent(); } private void Refresh(bool isNavigationIntercepted) { - var locationPath = UriHelper.ToBaseRelativePath(_baseUri, _locationAbsolute); + var locationPath = NavigationManager.ToBaseRelativePath(_locationAbsolute); locationPath = StringUntilAny(locationPath, _queryOrHashStartChar); var context = new RouteContext(locationPath); Routes.Route(context); @@ -120,19 +120,19 @@ namespace Microsoft.AspNetCore.Components.Routing } else { - if (!isNavigationIntercepted && NotFoundContent != null) + if (!isNavigationIntercepted && NotFound != null) { - Log.DisplayingNotFoundContent(_logger, locationPath, _baseUri); + Log.DisplayingNotFound(_logger, locationPath, _baseUri); // We did not find a Component that matches the route. - // Only show the NotFoundContent if the application developer programatically got us here i.e we did not + // Only show the NotFound 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(NotFoundContent); + _renderHandle.Render(NotFound); } else { Log.NavigatingToExternalUri(_logger, _locationAbsolute, locationPath, _baseUri); - UriHelper.NavigateTo(_locationAbsolute, forceLoad: true); + NavigationManager.NavigateTo(_locationAbsolute, forceLoad: true); } } } @@ -159,8 +159,8 @@ namespace Microsoft.AspNetCore.Components.Routing private static class Log { - private static readonly Action _displayingNotFoundContent = - LoggerMessage.Define(LogLevel.Debug, new EventId(1, "DisplayingNotFoundContent"), $"Displaying {nameof(NotFoundContent)} because path '{{Path}}' with base URI '{{BaseUri}}' does not match any component route"); + 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}'"); @@ -168,9 +168,9 @@ namespace Microsoft.AspNetCore.Components.Routing 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 DisplayingNotFoundContent(ILogger logger, string path, string baseUri) + internal static void DisplayingNotFound(ILogger logger, string path, string baseUri) { - _displayingNotFoundContent(logger, path, baseUri, null); + _displayingNotFound(logger, path, baseUri, null); } internal static void NavigatingToComponent(ILogger logger, Type componentType, string path, string baseUri) diff --git a/src/Components/Components/src/RuntimeHelpers.cs b/src/Components/Components/src/RuntimeHelpers.cs deleted file mode 100644 index 6e5823fec2..0000000000 --- a/src/Components/Components/src/RuntimeHelpers.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; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Components -{ - /// - /// 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. - /// - /// - /// - /// - // - // This method is used to create an expression binding site with a compile-time known type. This helps with providing - // good error messages, as well as proper method-group-to-delegate conversion when assigning component parameters. - 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/UIEventArgs.cs b/src/Components/Components/src/UIEventArgs.cs deleted file mode 100644 index 3da5e6bc22..0000000000 --- a/src/Components/Components/src/UIEventArgs.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. - -namespace Microsoft.AspNetCore.Components -{ - /// - /// Supplies information about an event that is being raised. - /// - public class UIEventArgs - { - /// - /// An empty instance of . - /// - public static readonly UIEventArgs Empty = new UIEventArgs(); - - /// - /// Gets or sets the type of the event. - /// - public string Type { get; set; } - } - - /// - /// Supplies information about an input change event that is being raised. - /// - public class UIChangeEventArgs : UIEventArgs - { - /// - /// Gets or sets the new value of the input. This may be a - /// or a . - /// - public object Value { get; set; } - } - - /// - /// Supplies information about an clipboard event that is being raised. - /// - public class UIClipboardEventArgs : UIEventArgs - { - } - - /// - /// Supplies information about an drag event that is being raised. - /// - public class UIDragEventArgs : UIMouseEventArgs - { - /// - /// The data that underlies a drag-and-drop operation, known as the drag data store. - /// See . - /// - public DataTransfer DataTransfer { get; set; } - } - - /// - /// The object is used to hold the data that is being dragged during a drag and drop operation. - /// It may hold one or more , each of one or more data types. - /// For more information about drag and drop, see HTML Drag and Drop API. - /// - public class DataTransfer - { - /// - /// Gets the type of drag-and-drop operation currently selected or sets the operation to a new type. - /// The value must be none, copy, link or move. - /// - public string DropEffect { get; set; } - - /// - /// Provides all of the types of operations that are possible. - /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized. - /// - public string EffectAllowed { get; set; } - - /// - /// Contains a list of all the local files available on the data transfer. - /// If the drag operation doesn't involve dragging files, this property is an empty list. - /// - public string[] Files { get; set; } - - /// - /// Gives a array which is a list of all of the drag data. - /// - public UIDataTransferItem[] Items { get; set; } - - /// - /// An array of giving the formats that were set in the dragstart event. - /// - public string[] Types { get; set; } - } - - /// - /// The object represents one drag data item. - /// During a drag operation, each drag event has a dataTransfer property which contains a list of drag data items. - /// Each item in the list is a object. - /// - public class UIDataTransferItem - { - /// - /// The kind of drag data item, string or file - /// - public string Kind { get; set; } - - /// - /// The drag data item's type, typically a MIME type - /// - public string Type { get; set; } - } - - /// - /// Supplies information about an error event that is being raised. - /// - public class UIErrorEventArgs : UIEventArgs - { - /// - /// Gets a a human-readable error message describing the problem. - /// - public string Message { get; set; } - - /// - /// Gets the name of the script file in which the error occurred. - /// - public string Filename { get; set; } - - /// - /// Gets the line number of the script file on which the error occurred. - /// - public int Lineno { get; set; } - - /// - /// Gets the column number of the script file on which the error occurred. - /// - public int Colno { get; set; } - } - - /// - /// Supplies information about a focus event that is being raised. - /// - public class UIFocusEventArgs : UIEventArgs - { - // Not including support for 'relatedTarget' since we don't have a good way to represent it. - // see: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent - } - - /// - /// Supplies information about a keyboard event that is being raised. - /// - public class UIKeyboardEventArgs : UIEventArgs - { - /// - /// The key value of the key represented by the event. - /// If the value has a printed representation, this attribute's value is the same as the char attribute. - /// Otherwise, it's one of the key value strings specified in 'Key values'. - /// If the key can't be identified, this is the string "Unidentified" - /// - public string Key { get; set; } - - /// - /// Holds a string that identifies the physical key being pressed. - /// The value is not affected by the current keyboard layout or modifier state, so a particular key will always return the same value. - /// - public string Code { get; set; } - - /// - /// The location of the key on the device. - /// - public float Location { get; set; } - - /// - /// true if a key has been depressed long enough to trigger key repetition, otherwise false. - /// - public bool Repeat { get; set; } - - /// - /// true if the control key was down when the event was fired. false otherwise. - /// - public bool CtrlKey { get; set; } - - /// - /// true if the shift key was down when the event was fired. false otherwise. - /// - public bool ShiftKey { get; set; } - - /// - /// true if the alt key was down when the event was fired. false otherwise. - /// - public bool AltKey { get; set; } - - /// - /// true if the meta key was down when the event was fired. false otherwise. - /// - public bool MetaKey { get; set; } - } - - /// - /// Supplies information about a mouse event that is being raised. - /// - public class UIMouseEventArgs : UIEventArgs - { - /// - /// A count of consecutive clicks that happened in a short amount of time, incremented by one. - /// - public long Detail { get; set; } - - /// - /// The X coordinate of the mouse pointer in global (screen) coordinates. - /// - public double ScreenX { get; set; } - - /// - /// The Y coordinate of the mouse pointer in global (screen) coordinates. - /// - public double ScreenY { get; set; } - - /// - /// The X coordinate of the mouse pointer in local (DOM content) coordinates. - /// - public double ClientX { get; set; } - - /// - /// The Y coordinate of the mouse pointer in local (DOM content) coordinates. - /// - public double ClientY { get; set; } - - /// - /// The button number that was pressed when the mouse event was fired: - /// Left button=0, - /// middle button=1 (if present), - /// right button=2. - /// For mice configured for left handed use in which the button actions are reversed the values are instead read from right to left. - /// - public long Button { get; set; } - - /// - /// The buttons being pressed when the mouse event was fired: - /// Left button=1, - /// Right button=2, - /// Middle (wheel) button=4, - /// 4th button (typically, "Browser Back" button)=8, - /// 5th button (typically, "Browser Forward" button)=16. - /// If two or more buttons are pressed, returns the logical sum of the values. - /// E.g., if Left button and Right button are pressed, returns 3 (=1 | 2). - /// - public long Buttons { get; set; } - - /// - /// true if the control key was down when the event was fired. false otherwise. - /// - public bool CtrlKey { get; set; } - - /// - /// true if the shift key was down when the event was fired. false otherwise. - /// - public bool ShiftKey { get; set; } - - /// - /// true if the alt key was down when the event was fired. false otherwise. - /// - public bool AltKey { get; set; } - - /// - /// true if the meta key was down when the event was fired. false otherwise. - /// - public bool MetaKey { get; set; } - } - - /// - /// Supplies information about a mouse event that is being raised. - /// - public class UIPointerEventArgs : UIMouseEventArgs - { - /// - /// A unique identifier for the pointer causing the event. - /// - public long PointerId { get; set; } - - /// - /// The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer. - /// - public float Width { get; set; } - - /// - /// The height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer. - /// - public float Height { get; set; } - - /// - /// The normalized pressure of the pointer input in the range of 0 to 1, - /// where 0 and 1 represent the minimum and maximum pressure the hardware is capable of detecting, respectively. - /// - public float Pressure { get; set; } - - /// - /// The plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane - /// and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis. - /// - public float TiltX { get; set; } - - /// - /// The plane angle (in degrees, in the range of -90 to 90) between the X-Z plane - /// and the plane containing both the transducer (e.g. pen stylus) axis and the X axis. - /// - public float TiltY { get; set; } - - /// - /// Indicates the device type that caused the event. - /// Must be one of the strings mouse, pen or touch, or an empty string. - /// - public string PointerType { get; set; } - - /// - /// Indicates if the pointer represents the primary pointer of this pointer type. - /// - public bool IsPrimary { get; set; } - } - - /// - /// Supplies information about a progress event that is being raised. - /// - public class UIProgressEventArgs : UIEventArgs - { - /// - /// Whether or not the total size of the transfer is known. - /// - public bool LengthComputable { get; set; } - - /// - /// The number of bytes transferred since the beginning of the operation. - /// This doesn't include headers and other overhead, but only the content itself. - /// - public long Loaded { get; set; } - - /// - /// The total number of bytes of content that will be transferred during the operation. - /// If the total size is unknown, this value is zero. - /// - public long Total { get; set; } - } - - /// - /// Supplies information about a touch event that is being raised. - /// - public class UITouchEventArgs : UIEventArgs - { - /// - /// A count of consecutive clicks that happened in a short amount of time, incremented by one. - /// - public long Detail { get; set; } - - /// - /// A list of for every point of contact currently touching the surface. - /// - public UITouchPoint[] Touches { get; set; } - - /// - /// A list of for every point of contact that is touching the surface and started on the element that is the target of the current event. - /// - public UITouchPoint[] TargetTouches { get; set; } - - /// - /// A list of Touches for every point of contact which contributed to the event. - /// For the touchstart event this must be a list of the touch points that just became active with the current event. - /// For the touchmove event this must be a list of the touch points that have moved since the last event. - /// For the touchend and touchcancel events this must be a list of the touch points that have just been removed from the surface. - /// - public UITouchPoint[] ChangedTouches { get; set; } - - /// - /// true if the control key was down when the event was fired. false otherwise. - /// - public bool CtrlKey { get; set; } - - /// - /// true if the shift key was down when the event was fired. false otherwise. - /// - public bool ShiftKey { get; set; } - - /// - /// true if the alt key was down when the event was fired. false otherwise. - /// - public bool AltKey { get; set; } - - /// - /// true if the meta key was down when the event was fired. false otherwise. - /// - public bool MetaKey { get; set; } - } - - /// - /// Represents a single contact point on a touch-sensitive device. - /// The contact point is commonly a finger or stylus and the device may be a touchscreen or trackpad. - /// - public class UITouchPoint - { - /// - /// A unique identifier for this Touch object. - /// A given touch point (say, by a finger) will have the same identifier for the duration of its movement around the surface. - /// This lets you ensure that you're tracking the same touch all the time. - /// - public long Identifier { get; set; } - - /// - /// The X coordinate of the touch point relative to the left edge of the screen. - /// - public double ScreenX { get; set; } - - /// - /// The Y coordinate of the touch point relative to the top edge of the screen. - /// - public double ScreenY { get; set; } - - /// - /// The X coordinate of the touch point relative to the left edge of the browser viewport, not including any scroll offset. - /// - public double ClientX { get; set; } - - /// - /// The Y coordinate of the touch point relative to the top edge of the browser viewport, not including any scroll offset. - /// - public double ClientY { get; set; } - - /// - /// The X coordinate of the touch point relative to the left edge of the document. - /// Unlike , this value includes the horizontal scroll offset, if any. - /// - public double PageX { get; set; } - - /// - /// The Y coordinate of the touch point relative to the top of the document. - /// Unlike , this value includes the vertical scroll offset, if any. - /// - public double PageY { get; set; } - } - - /// - /// Supplies information about a mouse wheel event that is being raised. - /// - public class UIWheelEventArgs : UIMouseEventArgs - { - /// - /// The horizontal scroll amount. - /// - public double DeltaX { get; set; } - - /// - /// The vertical scroll amount. - /// - public double DeltaY { get; set; } - - /// - /// The scroll amount for the z-axis. - /// - public double DeltaZ { get; set; } - - /// - /// The unit of the delta values scroll amount. - /// - public long DeltaMode { get; set; } - } -} diff --git a/src/Components/Components/src/UriHelperBase.cs b/src/Components/Components/src/UriHelperBase.cs deleted file mode 100644 index 3b8f091045..0000000000 --- a/src/Components/Components/src/UriHelperBase.cs +++ /dev/null @@ -1,230 +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 -{ - /// - /// A base class for implementations. - /// - public abstract class UriHelperBase : IUriHelper - { - private EventHandler _onLocationChanged; - - /// - /// An event that fires when the navigation location has changed. - /// - public event EventHandler OnLocationChanged - { - add - { - AssertInitialized(); - _onLocationChanged += value; - } - remove - { - _onLocationChanged -= value; - } - } - - // For the baseUri it's worth storing both the string form and Uri form and - // keeping them in sync. These are always represented as absolute URIs with - // a trailing slash. - private Uri _baseUri; - private string _baseUriString; - - // The URI. Always represented an absolute URI. - private string _uri; - - private bool _isInitialized; - - /// - /// Navigates to the specified URI. - /// - /// The destination URI. This can be absolute, or relative to the base URI - /// (as returned by ). - public void NavigateTo(string uri) - { - NavigateTo(uri, forceLoad: false); - } - - /// - /// 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) - { - 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 this method to dynamically calculate these values. - /// - public virtual void InitializeState(string uriAbsolute, string baseUriAbsolute) - { - if (uriAbsolute == null) - { - throw new ArgumentNullException(nameof(uriAbsolute)); - } - - if (baseUriAbsolute == null) - { - throw new ArgumentNullException(nameof(baseUriAbsolute)); - } - - if (_isInitialized) - { - throw new InvalidOperationException($"'{typeof(UriHelperBase).Name}' already initialized."); - } - _isInitialized = true; - - SetAbsoluteUri(uriAbsolute); - SetAbsoluteBaseUri(baseUriAbsolute); - } - - /// - /// Allows derived classes to lazyly self initialize. It does nothing unless overriden. - /// - protected virtual void EnsureInitialized() - { - } - - /// - /// Gets the current absolute URI. - /// - /// The current absolute URI. - public string GetAbsoluteUri() - { - AssertInitialized(); - return _uri; - } - - /// - /// Gets the base URI (with trailing slash) that can be prepended before relative URI paths to - /// produce an absolute URI. Typically this corresponds to the 'href' attribute on the - /// document's <base> element. - /// - /// The URI prefix, which has a trailing slash. - public virtual string GetBaseUri() - { - AssertInitialized(); - return _baseUriString; - } - - /// - /// 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 href) - { - AssertInitialized(); - return new Uri(_baseUri, href); - } - - /// - /// Given a base URI (e.g., one previously returned by ), - /// converts an absolute URI into one relative to the base URI prefix. - /// - /// - /// The base URI prefix (e.g., previously returned by ). - /// - /// An absolute URI that is within the space of the base URI. - /// A relative URI path. - public string ToBaseRelativePath(string baseUri, string locationAbsolute) - { - if (locationAbsolute.StartsWith(baseUri, 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 locationAbsolute.Substring(baseUri.Length); - } - - var hashIndex = locationAbsolute.IndexOf('#'); - var locationAbsoluteNoHash = hashIndex < 0 ? locationAbsolute : locationAbsolute.Substring(0, hashIndex); - if ($"{locationAbsoluteNoHash}/".Equals(baseUri, 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 locationAbsolute.Substring(baseUri.Length - 1); - } - - var message = $"The URI '{locationAbsolute}' is not contained by the base URI '{baseUri}'."; - throw new ArgumentException(message); - } - - /// - /// Set the URI to the provided value. - /// - /// The URI. Must be an absolute URI. - /// - /// Calling does not trigger . - /// - protected void SetAbsoluteUri(string uri) - { - _uri = uri; - } - - /// - /// Sets the base URI to the provided value (after normalization). - /// - /// The base URI. Must be an absolute URI. - /// - /// Calling does not trigger . - /// - protected void SetAbsoluteBaseUri(string baseUri) - { - if (baseUri != null) - { - var lastSlashIndex = baseUri.LastIndexOf('/'); - if (lastSlashIndex >= 0) - { - baseUri = baseUri.Substring(0, lastSlashIndex + 1); - } - } - - _baseUriString = baseUri ?? "/"; - _baseUri = new Uri(_baseUriString); - } - - /// - /// Triggers the event with the current URI value. - /// - protected void TriggerOnLocationChanged(bool isinterceptedLink) - { - _onLocationChanged?.Invoke(this, new LocationChangedEventArgs(_uri, isinterceptedLink)); - } - - private void AssertInitialized() - { - if (!_isInitialized) - { - EnsureInitialized(); - } - - if (!_isInitialized) - { - throw new InvalidOperationException($"'{GetType().Name}' has not been initialized."); - } - } - } -} diff --git a/src/Components/Components/test/Auth/AuthorizeViewTest.cs b/src/Components/Components/test/Auth/AuthorizeViewTest.cs index d87eb9eaeb..848e68e815 100644 --- a/src/Components/Components/test/Auth/AuthorizeViewTest.cs +++ b/src/Components/Components/test/Auth/AuthorizeViewTest.cs @@ -53,13 +53,13 @@ namespace Microsoft.AspNetCore.Components } [Fact] - public void RendersNotAuthorizedContentIfNotAuthorized() + public void RendersNotAuthorizedIfNotAuthorized() { // Arrange var authorizationService = new TestAuthorizationService(); var renderer = CreateTestRenderer(authorizationService); var rootComponent = WrapInAuthorizeView( - notAuthorizedContent: + notAuthorized: context => builder => builder.AddContent(0, $"You are not authorized, even though we know you are {context.User.Identity.Name}")); rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Components } [Fact] - public void RendersNothingIfAuthorizedButNoChildContentOrAuthorizedContentProvided() + public void RendersNothingIfAuthorizedButNoChildContentOrAuthorizedProvided() { // Arrange var authorizationService = new TestAuthorizationService(); @@ -152,14 +152,14 @@ namespace Microsoft.AspNetCore.Components } [Fact] - public void RendersAuthorizedContentIfAuthorized() + public void RendersAuthorizedIfAuthorized() { // Arrange var authorizationService = new TestAuthorizationService(); authorizationService.NextResult = AuthorizationResult.Success(); var renderer = CreateTestRenderer(authorizationService); var rootComponent = WrapInAuthorizeView( - authorizedContent: context => builder => + authorized: context => builder => builder.AddContent(0, $"You are authenticated as {context.User.Identity.Name}")); rootComponent.AuthenticationState = CreateAuthenticationState("Nellie"); @@ -235,13 +235,13 @@ namespace Microsoft.AspNetCore.Components } [Fact] - public void ThrowsIfBothChildContentAndAuthorizedContentProvided() + public void ThrowsIfBothChildContentAndAuthorizedProvided() { // Arrange var authorizationService = new TestAuthorizationService(); var renderer = CreateTestRenderer(authorizationService); var rootComponent = WrapInAuthorizeView( - authorizedContent: context => builder => { }, + authorized: context => builder => { }, childContent: context => builder => { }); // Act/Assert @@ -260,7 +260,7 @@ namespace Microsoft.AspNetCore.Components var renderer = CreateTestRenderer(authorizationService); renderer.OnUpdateDisplayComplete = () => { @event.Set(); }; var rootComponent = WrapInAuthorizeView( - notAuthorizedContent: + notAuthorized: context => builder => builder.AddContent(0, "You are not authorized")); var authTcs = new TaskCompletionSource(); rootComponent.AuthenticationState = authTcs.Task; @@ -293,7 +293,7 @@ namespace Microsoft.AspNetCore.Components } [Fact] - public void RendersAuthorizingContentUntilAuthorizationCompleted() + public void RendersAuthorizingUntilAuthorizationCompleted() { // Arrange var @event = new ManualResetEventSlim(); @@ -302,8 +302,8 @@ namespace Microsoft.AspNetCore.Components var renderer = CreateTestRenderer(authorizationService); renderer.OnUpdateDisplayComplete = () => { @event.Set(); }; var rootComponent = WrapInAuthorizeView( - authorizingContent: builder => builder.AddContent(0, "Auth pending..."), - authorizedContent: context => builder => builder.AddContent(0, $"Hello, {context.User.Identity.Name}!")); + 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; @@ -447,9 +447,9 @@ namespace Microsoft.AspNetCore.Components private static TestAuthStateProviderComponent WrapInAuthorizeView( RenderFragment childContent = null, - RenderFragment authorizedContent = null, - RenderFragment notAuthorizedContent = null, - RenderFragment authorizingContent = null, + RenderFragment authorized = null, + RenderFragment notAuthorized = null, + RenderFragment authorizing = null, string policy = null, string roles = null, object resource = null) @@ -458,9 +458,9 @@ namespace Microsoft.AspNetCore.Components { builder.OpenComponent(0); builder.AddAttribute(1, nameof(AuthorizeView.ChildContent), childContent); - builder.AddAttribute(2, nameof(AuthorizeView.Authorized), authorizedContent); - builder.AddAttribute(3, nameof(AuthorizeView.NotAuthorized), notAuthorizedContent); - builder.AddAttribute(4, nameof(AuthorizeView.Authorizing), authorizingContent); + 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); @@ -484,10 +484,10 @@ namespace Microsoft.AspNetCore.Components { builder.OpenComponent>>(0); builder.AddAttribute(1, nameof(CascadingValue>.Value), AuthenticationState); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, (RenderFragment)(builder => + builder.AddAttribute(2, "ChildContent", (RenderFragment)(builder => { builder.OpenComponent(0); - builder.AddAttribute(1, RenderTreeBuilder.ChildContent, _childContent); + builder.AddAttribute(1, "ChildContent", _childContent); builder.CloseComponent(); })); builder.CloseComponent(); diff --git a/src/Components/Components/test/Auth/CascadingAuthenticationStateTest.cs b/src/Components/Components/test/Auth/CascadingAuthenticationStateTest.cs index d21665249e..21a269932c 100644 --- a/src/Components/Components/test/Auth/CascadingAuthenticationStateTest.cs +++ b/src/Components/Components/test/Auth/CascadingAuthenticationStateTest.cs @@ -180,7 +180,7 @@ namespace Microsoft.AspNetCore.Components protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenComponent(0); - builder.AddAttribute(1, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(1, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent(0); childBuilder.CloseComponent(); diff --git a/src/Components/Components/test/CascadingParameterStateTest.cs b/src/Components/Components/test/CascadingParameterStateTest.cs index 12ed03a445..5931d9d6fc 100644 --- a/src/Components/Components/test/CascadingParameterStateTest.cs +++ b/src/Components/Components/test/CascadingParameterStateTest.cs @@ -386,7 +386,7 @@ namespace Microsoft.AspNetCore.Components.Test supplierParams.Add("Name", name); } - renderer.Dispatcher.InvokeAsync((Action)(() => supplier.SetParametersAsync(ParameterCollection.FromDictionary(supplierParams)))); + renderer.Dispatcher.InvokeAsync((Action)(() => supplier.SetParametersAsync(ParameterView.FromDictionary(supplierParams)))); return supplier; } @@ -427,7 +427,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } diff --git a/src/Components/Components/test/CascadingParameterTest.cs b/src/Components/Components/test/CascadingParameterTest.cs index 766a1bd3b4..1e05b98f68 100644 --- a/src/Components/Components/test/CascadingParameterTest.cs +++ b/src/Components/Components/test/CascadingParameterTest.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Components.Test { builder.OpenComponent>(0); builder.AddAttribute(1, "Value", "Hello"); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent>(0); childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.Test { builder.OpenComponent>(0); builder.AddAttribute(1, "Value", "Hello"); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent>(0); childBuilder.AddAttribute(1, "RegularParameter", regularParameterValue); @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Components.Test { builder.OpenComponent>(0); builder.AddAttribute(1, "Value", providedValue); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent>(0); childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.Components.Test { builder.OpenComponent>(0); builder.AddAttribute(1, "Value", "Unchanging value"); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent>(0); childBuilder.AddAttribute(1, "RegularParameter", "Goodbye"); @@ -192,12 +192,12 @@ namespace Microsoft.AspNetCore.Components.Test builder.OpenComponent>(0); builder.AddAttribute(1, "Value", 123); builder.AddAttribute(2, "IsFixed", true); - builder.AddAttribute(3, RenderTreeBuilder.ChildContent, new RenderFragment(builder2 => + 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, RenderTreeBuilder.ChildContent, new RenderFragment(builder3 => + builder2.AddAttribute(2, "ChildContent", new RenderFragment(builder3 => { if (displayNestedComponent) { @@ -258,7 +258,7 @@ namespace Microsoft.AspNetCore.Components.Test builder.OpenComponent>(0); builder.AddAttribute(1, "Value", providedValue); builder.AddAttribute(2, "IsFixed", true); - builder.AddAttribute(3, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(3, "ChildContent", new RenderFragment(childBuilder => { if (shouldIncludeChild) { @@ -383,7 +383,7 @@ namespace Microsoft.AspNetCore.Components.Test [CascadingParameter] T CascadingParameter { get; set; } [Parameter] public string RegularParameter { get; set; } - public override async Task SetParametersAsync(ParameterCollection parameters) + public override async Task SetParametersAsync(ParameterView parameters) { NumSetParametersCalls++; await base.SetParametersAsync(parameters); diff --git a/src/Components/Components/test/ComponentFactoryTest.cs b/src/Components/Components/test/ComponentFactoryTest.cs index 0d77c0f24a..4dd4de56e0 100644 --- a/src/Components/Components/test/ComponentFactoryTest.cs +++ b/src/Components/Components/test/ComponentFactoryTest.cs @@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Components throw new NotImplementedException(); } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { throw new NotImplementedException(); } @@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.Components throw new NotImplementedException(); } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { throw new NotImplementedException(); } @@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Components throw new NotImplementedException(); } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { throw new NotImplementedException(); } diff --git a/src/Components/Components/test/DependencyInjectionTest.cs b/src/Components/Components/test/DependencyInjectionTest.cs index fedbcba993..2a77c75325 100644 --- a/src/Components/Components/test/DependencyInjectionTest.cs +++ b/src/Components/Components/test/DependencyInjectionTest.cs @@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } } diff --git a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs b/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs index 220e9285ab..8df5092112 100644 --- a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs +++ b/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Components var binder = EventCallback.Factory.CreateBinder(component, setter, value); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "not-an-integer!", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "not-an-integer!", }); Assert.Equal(17, value); // Setter not called Assert.Equal(1, component.Count); @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Components var binder = EventCallback.Factory.CreateBinder(component, setter, value); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = string.Empty, }); + 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); @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Components // Act await Assert.ThrowsAsync(() => { - return binder.InvokeAsync(new UIChangeEventArgs() { Value = "18", }); + return binder.InvokeAsync(new ChangeEventArgs() { Value = "18", }); }); Assert.Equal(1, component.Count); @@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Components var binder = EventCallback.Factory.CreateBinder(component, setter, value); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "not-an-integer!", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "not-an-integer!", }); Assert.Equal(17, value); // Setter not called Assert.Equal(1, component.Count); @@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Components var binder = EventCallback.Factory.CreateBinder(component, setter, value); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "", }); Assert.Null(value); // Setter called Assert.Equal(1, component.Count); @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = "bye"; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue, }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue, }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = true; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = true, }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = true, }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (bool?)true; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = true, }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = true, }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = 42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (int?)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (long)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -225,7 +225,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (long?)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -244,7 +244,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (float)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -263,7 +263,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (float?)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -282,7 +282,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (double)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -301,7 +301,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (double?)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (decimal)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -339,7 +339,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = (decimal?)42; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -358,7 +358,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = AttributeTargets.Class; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -377,7 +377,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = AttributeTargets.Class; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -396,7 +396,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -415,7 +415,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -435,7 +435,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -455,7 +455,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -474,7 +474,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -493,7 +493,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -513,7 +513,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -533,7 +533,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -553,7 +553,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = Guid.NewGuid(); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -573,7 +573,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = Guid.NewGuid(); // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -592,7 +592,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = new SecretMessage() { Message = "TypeConverter may be old, but it still works!", }; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); Assert.Equal(expectedValue.Message, value.Message); Assert.Equal(1, component.Count); @@ -627,7 +627,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = 42_000; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42 000,00", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42 000,00", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -646,7 +646,7 @@ namespace Microsoft.AspNetCore.Components var expectedValue = 42_000; // Act - await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42,000.00", }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = "42,000.00", }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -667,7 +667,7 @@ namespace Microsoft.AspNetCore.Components throw new System.NotImplementedException(); } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { throw new System.NotImplementedException(); } diff --git a/src/Components/Components/test/EventCallbackFactoryTest.cs b/src/Components/Components/test/EventCallbackFactoryTest.cs index dc9a3bfd30..69b7bfa748 100644 --- a/src/Components/Components/test/EventCallbackFactoryTest.cs +++ b/src/Components/Components/test/EventCallbackFactoryTest.cs @@ -645,7 +645,7 @@ namespace Microsoft.AspNetCore.Components throw new NotImplementedException(); } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { throw new NotImplementedException(); } diff --git a/src/Components/Components/test/EventCallbackTest.cs b/src/Components/Components/test/EventCallbackTest.cs index e390735fa8..25405c2180 100644 --- a/src/Components/Components/test/EventCallbackTest.cs +++ b/src/Components/Components/test/EventCallbackTest.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Components public async Task EventCallbackOfT_Default() { // Arrange - var callback = default(EventCallback); + var callback = default(EventCallback); // Act & Assert (Does not throw) await callback.InvokeAsync(null); @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Components { // Arrange int runCount = 0; - var callback = new EventCallback(null, (Action)(() => runCount++)); + var callback = new EventCallback(null, (Action)(() => runCount++)); // Act await callback.InvokeAsync(null); @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Components var callback = new EventCallback(component, (Action)(() => runCount++)); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -104,8 +104,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); // Act await callback.InvokeAsync(null); @@ -124,11 +124,11 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -164,8 +164,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); // Act & Assert await Assert.ThrowsAsync(() => @@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Components var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -217,8 +217,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); // Act await callback.InvokeAsync(null); @@ -237,11 +237,11 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -277,8 +277,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); // Act & Assert await Assert.ThrowsAsync(() => @@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); + var callback = new EventCallback(component, (Action)(() => runCount++)); // Act await callback.InvokeAsync(null); @@ -312,10 +312,10 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - var callback = new EventCallback(component, (Action)(() => runCount++)); + var callback = new EventCallback(component, (Action)(() => runCount++)); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -330,8 +330,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); // Act await callback.InvokeAsync(null); @@ -350,11 +350,11 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Action)((e) => { arg = e; runCount++; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -370,7 +370,7 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); + var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); // Act await callback.InvokeAsync(null); @@ -388,10 +388,10 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); + var callback = new EventCallback(component, (Func)(() => { runCount++; return Task.CompletedTask; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -406,8 +406,8 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); // Act await callback.InvokeAsync(null); @@ -426,11 +426,11 @@ namespace Microsoft.AspNetCore.Components var component = new EventCountingComponent(); int runCount = 0; - UIEventArgs arg = null; - var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); + EventArgs arg = null; + var callback = new EventCallback(component, (Func)((e) => { arg = e; runCount++; return Task.CompletedTask; })); // Act - await callback.InvokeAsync(new UIEventArgs()); + await callback.InvokeAsync(new EventArgs()); // Assert @@ -451,7 +451,7 @@ namespace Microsoft.AspNetCore.Components public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) => throw new NotImplementedException(); + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } } } diff --git a/src/Components/Components/test/Forms/ValidationMessageStoreTest.cs b/src/Components/Components/test/Forms/ValidationMessageStoreTest.cs index 75e4ef3452..5264e254bd 100644 --- a/src/Components/Components/test/Forms/ValidationMessageStoreTest.cs +++ b/src/Components/Components/test/Forms/ValidationMessageStoreTest.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Components.Forms } [Fact] - public void CanAddMessagesByRange() + public void CanAddMessagesMultiple() { // Arrange var messages = new ValidationMessageStore(new EditContext(new object())); @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Components.Forms var entries = new[] { "A", "B", "C" }; // Act - messages.AddRange(field1, entries); + messages.Add(field1, entries); // Assert Assert.Equal(entries, messages[field1]); diff --git a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj b/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj index fc08c77c6e..e97f75fd2a 100644 --- a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj +++ b/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj @@ -8,7 +8,6 @@ - diff --git a/src/Components/Components/test/NavigationManagerTest.cs b/src/Components/Components/test/NavigationManagerTest.cs new file mode 100644 index 0000000000..9b857bb044 --- /dev/null +++ b/src/Components/Components/test/NavigationManagerTest.cs @@ -0,0 +1,117 @@ +// Copyright (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 new file mode 100644 index 0000000000..155231b40b --- /dev/null +++ b/src/Components/Components/test/OwningComponentBaseTest.cs @@ -0,0 +1,61 @@ +// Copyright (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/PageDisplayTest.cs b/src/Components/Components/test/PageDisplayTest.cs index e73e7e7083..9b28d95d23 100644 --- a/src/Components/Components/test/PageDisplayTest.cs +++ b/src/Components/Components/test/PageDisplayTest.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Components.Test public void DisplaysComponentInsideLayout() { // Arrange/Act - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(ComponentWithLayout) } }))); @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Components.Test public void DisplaysComponentInsideNestedLayout() { // Arrange/Act - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(ComponentWithNestedLayout) } }))); @@ -111,13 +111,13 @@ namespace Microsoft.AspNetCore.Components.Test public void CanChangeDisplayedPageWithSameLayout() { // Arrange - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(ComponentWithLayout) } }))); // Act - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(DifferentComponentWithLayout) } }))); @@ -162,13 +162,13 @@ namespace Microsoft.AspNetCore.Components.Test public void CanChangeDisplayedPageWithDifferentLayout() { // Arrange - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(ComponentWithLayout) } }))); // Act - _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterCollection.FromDictionary(new Dictionary + _renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary { { nameof(PageDisplay.Page), typeof(ComponentWithNestedLayout) } }))); diff --git a/src/Components/Components/test/ParameterCollectionAssignmentExtensionsTest.cs b/src/Components/Components/test/ParameterViewTest.Assignment.cs similarity index 84% rename from src/Components/Components/test/ParameterCollectionAssignmentExtensionsTest.cs rename to src/Components/Components/test/ParameterViewTest.Assignment.cs index 131697490f..7c2056683a 100644 --- a/src/Components/Components/test/ParameterCollectionAssignmentExtensionsTest.cs +++ b/src/Components/Components/test/ParameterViewTest.Assignment.cs @@ -10,16 +10,16 @@ using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Test.Helpers; using Xunit; -namespace Microsoft.AspNetCore.Components.Test +namespace Microsoft.AspNetCore.Components { - public class ParameterCollectionAssignmentExtensionsTest + public partial class ParameterViewTest { [Fact] public void IncomingParameterMatchesAnnotatedPrivateProperty_SetsValue() { // Arrange var someObject = new object(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasInstanceProperties.IntProp), 123 }, { nameof(HasInstanceProperties.StringProp), "Hello" }, @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Components.Test var target = new HasInstanceProperties(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Equal(123, target.IntProp); @@ -40,14 +40,14 @@ namespace Microsoft.AspNetCore.Components.Test public void IncomingParameterMatchesDeclaredParameterCaseInsensitively_SetsValue() { // Arrange - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasInstanceProperties.IntProp).ToLowerInvariant(), 123 } }.Build(); var target = new HasInstanceProperties(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Equal(123, target.IntProp); @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Components.Test public void IncomingParameterMatchesInheritedDeclaredParameter_SetsValue() { // Arrange - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasInheritedProperties.IntProp), 123 }, { nameof(HasInheritedProperties.DerivedClassIntProp), 456 }, @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Components.Test var target = new HasInheritedProperties(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Equal(123, target.IntProp); @@ -84,10 +84,10 @@ namespace Microsoft.AspNetCore.Components.Test ObjectPropCurrentValue = existingObjectValue }; - var parameterCollection = new ParameterCollectionBuilder().Build(); + var parameters = new ParameterViewBuilder().Build(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Equal(456, target.IntProp); @@ -100,14 +100,14 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasPropertyWithoutParameterAttribute(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { "AnyOtherKey", 123 }, }.Build(); // Act var ex = Assert.Throws( - () => parameterCollection.SetParameterProperties(target)); + () => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -121,14 +121,14 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasPropertyWithoutParameterAttribute(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasPropertyWithoutParameterAttribute.IntProp), 123 }, }.Build(); // Act var ex = Assert.Throws( - () => parameterCollection.SetParameterProperties(target)); + () => parameters.SetParameterProperties(target)); // Assert Assert.Equal(default, target.IntProp); @@ -144,13 +144,13 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var target = new HasCaptureUnmatchedValuesProperty(); var value = new Dictionary(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues), value }, }.Build(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Same(value, target.CaptureUnmatchedValues); @@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasCaptureUnmatchedValuesProperty(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasCaptureUnmatchedValuesProperty.StringProp), "hi" }, { "test1", 123 }, @@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.Components.Test }.Build(); // Act - parameterCollection.SetParameterProperties(target); + parameters.SetParameterProperties(target); // Assert Assert.Equal("hi", target.StringProp); @@ -192,7 +192,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasCaptureUnmatchedValuesProperty(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasCaptureUnmatchedValuesProperty.CaptureUnmatchedValues), new Dictionary() }, { "test1", 123 }, @@ -200,7 +200,7 @@ namespace Microsoft.AspNetCore.Components.Test }.Build(); // Act - var ex = Assert.Throws(() => parameterCollection.SetParameterProperties(target)); + var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -216,7 +216,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasCaptureUnmatchedValuesProperty(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { "test2", 456 }, { "test1", 123 }, @@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.Components.Test }.Build(); // Act - var ex = Assert.Throws(() => parameterCollection.SetParameterProperties(target)); + var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -240,10 +240,10 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasDupliateCaptureUnmatchedValuesProperty(); - var parameterCollection = new ParameterCollectionBuilder().Build(); + var parameters = new ParameterViewBuilder().Build(); // Act - var ex = Assert.Throws(() => parameterCollection.SetParameterProperties(target)); + var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -261,10 +261,10 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasWrongTypeCaptureUnmatchedValuesProperty(); - var parameterCollection = new ParameterCollectionBuilder().Build(); + var parameters = new ParameterViewBuilder().Build(); // Act - var ex = Assert.Throws(() => parameterCollection.SetParameterProperties(target)); + var ex = Assert.Throws(() => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -279,7 +279,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var someObject = new object(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasInstanceProperties.IntProp), "string value" }, }.Build(); @@ -287,7 +287,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act var ex = Assert.Throws( - () => parameterCollection.SetParameterProperties(target)); + () => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -301,14 +301,14 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var target = new HasPropertyWhoseSetterThrows(); - var parameterCollection = new ParameterCollectionBuilder + var parameters = new ParameterViewBuilder { { nameof(HasPropertyWhoseSetterThrows.StringProp), "anything" }, }.Build(); // Act var ex = Assert.Throws( - () => parameterCollection.SetParameterProperties(target)); + () => parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -321,12 +321,12 @@ namespace Microsoft.AspNetCore.Components.Test public void DeclaredParametersVaryOnlyByCase_Throws() { // Arrange - var parameterCollection = new ParameterCollectionBuilder().Build(); + var parameters = new ParameterViewBuilder().Build(); var target = new HasParametersVaryingOnlyByCase(); // Act var ex = Assert.Throws(() => - parameterCollection.SetParameterProperties(target)); + parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -344,12 +344,12 @@ namespace Microsoft.AspNetCore.Components.Test // base class can legitimately depend on it for correct functioning. // Arrange - var parameterCollection = new ParameterCollectionBuilder().Build(); + var parameters = new ParameterViewBuilder().Build(); var target = new HasParameterClashingWithInherited(); // Act var ex = Assert.Throws(() => - parameterCollection.SetParameterProperties(target)); + parameters.SetParameterProperties(target)); // Assert Assert.Equal( @@ -358,6 +358,24 @@ namespace Microsoft.AspNetCore.Components.Test 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 { @@ -428,7 +446,7 @@ namespace Microsoft.AspNetCore.Components.Test [Parameter(CaptureUnmatchedValues = true)] public KeyValuePair[] CaptureUnmatchedValuesProp { get; set; } } - class ParameterCollectionBuilder : IEnumerable + class ParameterViewBuilder : IEnumerable { private readonly List<(string Name, object Value)> _keyValuePairs = new List<(string, object)>(); @@ -439,26 +457,17 @@ namespace Microsoft.AspNetCore.Components.Test public IEnumerator GetEnumerator() => throw new NotImplementedException(); - public ParameterCollection Build() + public ParameterView Build() { - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenComponent(0); foreach (var kvp in _keyValuePairs) { builder.AddAttribute(1, kvp.Name, kvp.Value); } builder.CloseComponent(); - return new ParameterCollection(builder.GetFrames().Array, ownerIndex: 0); + return new ParameterView(builder.GetFrames().Array, ownerIndex: 0); } } - - class FakeComponent : IComponent - { - public void Attach(RenderHandle renderHandle) - => throw new NotImplementedException(); - - public Task SetParametersAsync(ParameterCollection parameters) - => throw new NotImplementedException(); - } } } diff --git a/src/Components/Components/test/ParameterCollectionTest.cs b/src/Components/Components/test/ParameterViewTest.cs similarity index 79% rename from src/Components/Components/test/ParameterCollectionTest.cs rename to src/Components/Components/test/ParameterViewTest.cs index 9e9b8da975..cfb3191ca5 100644 --- a/src/Components/Components/test/ParameterCollectionTest.cs +++ b/src/Components/Components/test/ParameterViewTest.cs @@ -8,9 +8,9 @@ using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; using Xunit; -namespace Microsoft.AspNetCore.Components.Test +namespace Microsoft.AspNetCore.Components { - public class ParameterCollectionTest + public partial class ParameterViewTest { [Fact] public void CanInitializeUsingComponentWithNoDescendants() @@ -20,10 +20,10 @@ namespace Microsoft.AspNetCore.Components.Test { RenderTreeFrame.ChildComponent(0, typeof(FakeComponent)).WithComponentSubtreeLength(1) }; - var parameterCollection = new ParameterCollection(frames, 0); + var parameters = new ParameterView(frames, 0); // Assert - Assert.Empty(ToEnumerable(parameterCollection)); + Assert.Empty(ToEnumerable(parameters)); } [Fact] @@ -34,10 +34,10 @@ namespace Microsoft.AspNetCore.Components.Test { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(1) }; - var parameterCollection = new ParameterCollection(frames, 0); + var parameters = new ParameterView(frames, 0); // Assert - Assert.Empty(ToEnumerable(parameterCollection)); + Assert.Empty(ToEnumerable(parameters)); } [Fact] @@ -52,14 +52,14 @@ namespace Microsoft.AspNetCore.Components.Test 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 ParameterCollection doesn't attempt to read past the + // 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 parameterCollection = new ParameterCollection(frames, 0); + var parameters = new ParameterView(frames, 0); // Assert - Assert.Collection(ToEnumerable(parameterCollection), + Assert.Collection(ToEnumerable(parameters), AssertParameter("attribute 1", attribute1Value, false), AssertParameter("attribute 2", attribute2Value, false)); } @@ -78,10 +78,10 @@ namespace Microsoft.AspNetCore.Components.Test RenderTreeFrame.Element(3, "child element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(4, "child attribute", "some value") }; - var parameterCollection = new ParameterCollection(frames, 0); + var parameters = new ParameterView(frames, 0); // Assert - Assert.Collection(ToEnumerable(parameterCollection), + Assert.Collection(ToEnumerable(parameters), AssertParameter("attribute 1", attribute1Value, false), AssertParameter("attribute 2", attribute2Value, false)); } @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Components.Test var attribute1Value = new object(); var attribute2Value = new object(); var attribute3Value = new object(); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value) @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Components.Test }); // Assert - Assert.Collection(ToEnumerable(parameterCollection), + Assert.Collection(ToEnumerable(parameters), AssertParameter("attribute 1", attribute1Value, false), AssertParameter("attribute 2", attribute2Value, true), AssertParameter("attribute 3", attribute3Value, true)); @@ -114,14 +114,14 @@ namespace Microsoft.AspNetCore.Components.Test public void CanTryGetNonExistingValue() { // Arrange - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) }, 0); // Act - var didFind = parameterCollection.TryGetValue("nonexisting entry", out var value); + var didFind = parameters.TryGetValue("nonexisting entry", out var value); // Assert Assert.False(didFind); @@ -132,14 +132,14 @@ namespace Microsoft.AspNetCore.Components.Test public void CanTryGetExistingValueWithCorrectType() { // Arrange - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", "hello") }, 0); // Act - var didFind = parameterCollection.TryGetValue("my entry", out var value); + var didFind = parameters.TryGetValue("my entry", out var value); // Assert Assert.True(didFind); @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var myEntryValue = new object(); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", myEntryValue), @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Components.Test }, 0); // Act - var result = parameterCollection.GetValueOrDefault("my entry"); + var result = parameters.GetValueOrDefault("my entry"); // Assert Assert.Same(myEntryValue, result); @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var myEntryValue = new object(); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(1, "my entry", myEntryValue), @@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.Components.Test }, 0); // Act - var result = parameterCollection.GetValueOrDefault("my entry"); + var result = parameters.GetValueOrDefault("my entry"); // Assert: Picks first match Assert.Same(myEntryValue, result); @@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanGetValueOrDefault_WithNonExistingValue() { // Arrange - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) @@ -198,7 +198,7 @@ namespace Microsoft.AspNetCore.Components.Test }); // Act - var result = parameterCollection.GetValueOrDefault("nonexisting entry"); + var result = parameters.GetValueOrDefault("nonexisting entry"); // Assert Assert.Equal(default, result); @@ -209,14 +209,14 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var explicitDefaultValue = new DateTime(2018, 3, 20); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) }, 0); // Act - var result = parameterCollection.GetValueOrDefault("nonexisting entry", explicitDefaultValue); + var result = parameters.GetValueOrDefault("nonexisting entry", explicitDefaultValue); // Assert Assert.Equal(explicitDefaultValue, result); @@ -226,7 +226,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ThrowsIfTryGetExistingValueWithIncorrectType() { // Arrange - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", "hello") @@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert Assert.Throws(() => { - parameterCollection.TryGetValue("my entry", out var value); + parameters.TryGetValue("my entry", out var value); }); } @@ -246,7 +246,7 @@ namespace Microsoft.AspNetCore.Components.Test var dictionary = new Dictionary(); // Act - var collection = ParameterCollection.FromDictionary(dictionary); + var collection = ParameterView.FromDictionary(dictionary); // Assert Assert.Empty(collection.ToDictionary()); @@ -263,7 +263,7 @@ namespace Microsoft.AspNetCore.Components.Test }; // Act - var collection = ParameterCollection.FromDictionary(dictionary); + var collection = ParameterView.FromDictionary(dictionary); // Assert Assert.Equal(dictionary, collection.ToDictionary()); @@ -275,7 +275,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var entry2Value = new object(); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(0, "entry 1", "value 1"), @@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Components.Test }, 0); // Act - IReadOnlyDictionary dict = parameterCollection.ToDictionary(); + IReadOnlyDictionary dict = parameters.ToDictionary(); // Assert Assert.Collection(dict, @@ -304,7 +304,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var myEntryValue = new object(); - var parameterCollection = new ParameterCollection(new[] + var parameters = new ParameterView(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "unrelated value", new object()) @@ -316,13 +316,13 @@ namespace Microsoft.AspNetCore.Components.Test }); // Act - var result = parameterCollection.GetValueOrDefault("my entry"); + var result = parameters.GetValueOrDefault("my entry"); // Assert Assert.Same(myEntryValue, result); } - private Action AssertParameter(string expectedName, object expectedValue, bool expectedIsCascading) + private Action AssertParameter(string expectedName, object expectedValue, bool expectedIsCascading) { return parameter => { @@ -332,9 +332,9 @@ namespace Microsoft.AspNetCore.Components.Test }; } - public IEnumerable ToEnumerable(ParameterCollection parameterCollection) + public IEnumerable ToEnumerable(ParameterView parameters) { - foreach (var item in parameterCollection) + foreach (var item in parameters) { yield return item; } @@ -345,7 +345,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } diff --git a/src/Components/Components/test/RenderTreeBuilderTest.cs b/src/Components/Components/test/RenderTreeBuilderTest.cs index 3207c31e54..3e5cc0b969 100644 --- a/src/Components/Components/test/RenderTreeBuilderTest.cs +++ b/src/Components/Components/test/RenderTreeBuilderTest.cs @@ -16,20 +16,11 @@ namespace Microsoft.AspNetCore.Components.Test { public class RenderTreeBuilderTest { - [Fact] - public void RequiresNonnullRenderer() - { - Assert.Throws(() => - { - new RenderTreeBuilder(null); - }); - } - [Fact] public void StartsEmpty() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Assert var frames = builder.GetFrames(); @@ -41,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddText() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var nullString = (string)null; // Act @@ -61,7 +52,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddMarkup() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "some elem"); @@ -84,7 +75,7 @@ namespace Microsoft.AspNetCore.Components.Test // as opposed to calling builder.AddMarkupContent directly. // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act - can use either constructor or cast builder.AddContent(0, (MarkupString)"Some markup"); @@ -101,7 +92,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddNullMarkup() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.AddMarkupContent(0, null); @@ -116,7 +107,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddNonStringValueAsText() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var nullObject = (object)null; // Act @@ -134,7 +125,7 @@ namespace Microsoft.AspNetCore.Components.Test public void UnclosedElementsHaveNoSubtreeLength() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "my element"); @@ -148,7 +139,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ClosedEmptyElementsHaveSubtreeLengthOne() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.AddContent(0, "some frame so that the element isn't at position zero"); @@ -165,7 +156,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ClosedElementsHaveCorrectSubtreeLength() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "my element"); @@ -184,7 +175,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanNestElements() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.AddContent(0, "standalone text 1"); // 0: standalone text 1 @@ -224,8 +215,8 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddAttributes() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); - Action eventHandler = eventInfo => { }; + var builder = new RenderTreeBuilder(); + Action eventHandler = eventInfo => { }; // Act builder.OpenElement(0, "myelement"); // 0: eventHandler = eventInfo => { }; + var builder = new RenderTreeBuilder(); + Action eventHandler = eventInfo => { }; // Act builder.OpenElement(0, "myelement"); @@ -367,7 +358,7 @@ namespace Microsoft.AspNetCore.Components.Test private void CanAddMultipleAttributesTest(IEnumerable> attributes) { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "myelement"); @@ -389,7 +380,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddAttributeAtRoot() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -402,7 +393,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddDelegateAttributeAtRoot() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -415,7 +406,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddAttributeToText() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -430,14 +421,14 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddEventHandlerAttributeToText() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => { builder.OpenElement(0, "some element"); builder.AddContent(1, "hello"); - builder.AddAttribute(2, "name", new Action(eventInfo => { })); + builder.AddAttribute(2, "name", new Action(eventInfo => { })); }); } @@ -445,7 +436,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddAttributeToRegion() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -459,7 +450,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddAttributeToElementReferenceCapture() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -474,7 +465,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddAttributeToComponentReferenceCapture() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -489,7 +480,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddChildComponentsUsingGenericParam() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(10, "parent"); // 0: @@ -516,7 +507,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddChildComponentsUsingTypeArgument() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act var componentType = typeof(TestComponent); @@ -544,7 +535,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddRegions() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(10, "parent"); // 0: @@ -572,7 +563,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddFragments() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); RenderFragment fragment = fragmentBuilder => { fragmentBuilder.AddContent(0, "Hello from the fragment"); @@ -599,8 +590,8 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddElementReferenceCaptureInsideElement() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); - Action referenceCaptureAction = elementRef => { }; + var builder = new RenderTreeBuilder(); + Action referenceCaptureAction = elementReference => { }; // Act builder.OpenElement(0, "myelement"); // 0: (() => @@ -634,7 +625,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddElementReferenceCaptureInsideComponent() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -648,7 +639,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddElementReferenceCaptureInsideRegion() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -667,9 +658,9 @@ namespace Microsoft.AspNetCore.Components.Test // just works. // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); - Action referenceCaptureAction1 = elementRef => { }; - Action referenceCaptureAction2 = elementRef => { }; + var builder = new RenderTreeBuilder(); + Action referenceCaptureAction1 = elementReference => { }; + Action referenceCaptureAction2 = elementReference => { }; // Act builder.OpenElement(0, "myelement"); @@ -688,8 +679,8 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddComponentReferenceCaptureInsideComponent() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); - Action myAction = elementRef => { }; + var builder = new RenderTreeBuilder(); + Action myAction = elementReference => { }; // Act builder.OpenComponent(0); // 0: (() => @@ -723,7 +714,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddComponentReferenceCaptureInsideElement() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -737,7 +728,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddComponentReferenceCaptureInsideRegion() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert Assert.Throws(() => @@ -756,9 +747,9 @@ namespace Microsoft.AspNetCore.Components.Test // just works. // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); - Action referenceCaptureAction1 = elementRef => { }; - Action referenceCaptureAction2 = elementRef => { }; + var builder = new RenderTreeBuilder(); + Action referenceCaptureAction1 = elementReference => { }; + Action referenceCaptureAction2 = elementReference => { }; // Act builder.OpenComponent(0); @@ -777,7 +768,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanClear() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.AddContent(0, "some text"); @@ -794,7 +785,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_BoolTrue_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -812,7 +803,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_BoolFalse_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -831,7 +822,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_Bool_SetsAttributeValue(bool value) { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -849,7 +840,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_StringValue_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -867,7 +858,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_StringNull_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -886,7 +877,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_StringValue_SetsAttributeValue(string value) { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -904,9 +895,9 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventHandler_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); - var value = new Action((e) => { }); + var value = new Action((e) => { }); // Act builder.OpenElement(0, "elem"); @@ -924,11 +915,11 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_NullEventHandler_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "attr", (Action)null); + builder.AddAttribute(1, "attr", (Action)null); builder.CloseElement(); // Assert @@ -941,7 +932,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_Action_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var value = new Action(() => { }); @@ -961,7 +952,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_NullAction_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -974,7 +965,7 @@ namespace Microsoft.AspNetCore.Components.Test frame => AssertFrame.Element(frame, "elem", 1, 0)); } - public static TheoryData> EventHandlerValues => new TheoryData> + public static TheoryData> EventHandlerValues => new TheoryData> { null, (e) => { }, @@ -982,10 +973,10 @@ namespace Microsoft.AspNetCore.Components.Test [Theory] [MemberData(nameof(EventHandlerValues))] - public void AddAttribute_Component_EventHandlerValue_SetsAttributeValue(Action value) + public void AddAttribute_Component_EventHandlerValue_SetsAttributeValue(Action value) { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -1003,7 +994,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallback_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = new EventCallback(null, new Action(() => { })); // Act @@ -1022,7 +1013,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallback_Default_DoesNotAddFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = default(EventCallback); // Act @@ -1040,7 +1031,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallbackWithReceiver_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action(() => { })); @@ -1060,7 +1051,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_EventCallback_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action(() => { })); @@ -1080,7 +1071,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallbackOfT_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = new EventCallback(null, new Action((s) => { })); // Act @@ -1099,7 +1090,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallbackOfT_Default_DoesNotAddFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = default(EventCallback); // Act @@ -1117,7 +1108,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_EventCallbackWithReceiverOfT_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action((s) => { })); @@ -1137,7 +1128,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_EventCallbackOfT_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action((s) => { })); @@ -1157,7 +1148,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectBoolTrue_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -1175,7 +1166,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectBoolFalse_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -1194,7 +1185,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_ObjectBoolValue_SetsAttributeValue(bool value) { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -1212,7 +1203,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectStringValue_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -1230,7 +1221,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_ObjectStringValue_SetsAttributeValue() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -1248,9 +1239,9 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventHandler_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); - var value = new Action((e) => { }); + var value = new Action((e) => { }); // Act builder.OpenElement(0, "elem"); @@ -1268,9 +1259,9 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_ObjectUIEventHandleValue_SetsAttributeValue() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); - var value = new Action((e) => { }); + var value = new Action((e) => { }); // Act builder.OpenComponent(0); @@ -1288,7 +1279,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectAction_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var value = new Action(() => { }); @@ -1308,7 +1299,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_ObjectAction_SetsAttributeValue() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var value = new Action(() => { }); @@ -1328,7 +1319,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallback_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = new EventCallback(null, new Action(() => { })); // Act @@ -1347,7 +1338,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallback_Default_DoesNotAddFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = default(EventCallback); // Act @@ -1365,7 +1356,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallbackWithReceiver_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action(() => { })); @@ -1385,7 +1376,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Component_ObjectEventCallback_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action(() => { })); @@ -1405,7 +1396,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallbackOfT_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = new EventCallback(null, new Action((s) => { })); // Act @@ -1424,7 +1415,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallbackOfT_Default_DoesNotAddFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var callback = default(EventCallback); // Act @@ -1442,7 +1433,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectEventCallbackWithReceiverOfT_AddsFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var receiver = Mock.Of(); var callback = new EventCallback(receiver, new Action((s) => { })); @@ -1462,7 +1453,7 @@ namespace Microsoft.AspNetCore.Components.Test public void AddAttribute_Element_ObjectNull_IgnoresFrame() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -1479,7 +1470,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddKeyToElement() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var keyValue = new object(); // Act @@ -1505,7 +1496,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CanAddKeyToComponent() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); var keyValue = new object(); // Act @@ -1531,7 +1522,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddKeyOutsideComponentOrElement_TreeRoot() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert var ex = Assert.Throws(() => @@ -1545,7 +1536,7 @@ namespace Microsoft.AspNetCore.Components.Test public void CannotAddKeyOutsideComponentOrElement_RegionRoot() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act/Assert builder.OpenElement(0, "some element"); @@ -1561,7 +1552,7 @@ namespace Microsoft.AspNetCore.Components.Test public void IgnoresNullElementKey() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenElement(0, "elem"); @@ -1582,7 +1573,7 @@ namespace Microsoft.AspNetCore.Components.Test public void IgnoresNullComponentKey() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); // Act builder.OpenComponent(0); @@ -1603,7 +1594,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_DoesNotRemoveDuplicatesWithoutAddMultipleAttributes() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "id", "hi"); builder.AddAttribute(0, "id", "bye"); @@ -1625,9 +1616,9 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_StopsAtFirstNonAttributeFrame_Capture() { // Arrange - var capture = (Action)((_) => { }); + var capture = (Action)((_) => { }); - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "id", "hi"); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1652,7 +1643,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_StopsAtFirstNonAttributeFrame_Content() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "id", "hi"); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1677,7 +1668,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_CanRemoveDuplicateInsideElement() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "id", "hi"); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1700,7 +1691,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_CanRemoveDuplicateInsideComponent() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenComponent(0); builder.AddAttribute(0, "id", "hi"); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1724,7 +1715,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_SilentFrameFollowedBySameAttribute() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenComponent(0); builder.AddAttribute(0, "id", (string)null); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1747,7 +1738,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_DoesNotRemoveDuplicatesInsideChildElement() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "id", "hi"); builder.AddMultipleAttributes(0, new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1777,7 +1768,7 @@ namespace Microsoft.AspNetCore.Components.Test public void ProcessDuplicateAttributes_CanRemoveOverwrittenAttributes() { // Arrange - var builder = new RenderTreeBuilder(new TestRenderer()); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "div"); builder.AddAttribute(0, "A", "hi"); builder.AddAttribute(0, "2", new EventCallback(null, (Action)(() => { }))); @@ -1812,7 +1803,7 @@ namespace Microsoft.AspNetCore.Components.Test { public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } diff --git a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs b/src/Components/Components/test/RenderTreeDiffBuilderTest.cs index 28d9193ea0..503d45155f 100644 --- a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs +++ b/src/Components/Components/test/RenderTreeDiffBuilderTest.cs @@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Components.Test public RenderTreeDiffBuilderTest() { renderer = new FakeRenderer(); - oldTree = new RenderTreeBuilder(renderer); - newTree = new RenderTreeBuilder(renderer); + oldTree = new RenderTreeBuilder(); + newTree = new RenderTreeBuilder(); } void IDisposable.Dispose() @@ -217,7 +217,7 @@ namespace Microsoft.AspNetCore.Components.Test oldTree.SetKey("retained key"); oldTree.AddAttribute(1, "ParamName", "Param old value"); oldTree.CloseComponent(); - using var initial = new RenderTreeBuilder(renderer); + using var initial = new RenderTreeBuilder(); GetRenderedBatch(initial, oldTree, false); // Assign initial IDs var oldComponent = GetComponents(oldTree).Single(); @@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.Components.Test oldTree.CloseComponent(); // Instantiate initial components - using var initial = new RenderTreeBuilder(renderer); + using var initial = new RenderTreeBuilder(); GetRenderedBatch(initial, oldTree, false); var oldComponents = GetComponents(oldTree); @@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Components.Test oldTree.CloseComponent(); // Instantiate initial component - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + using var renderTreeBuilder = new RenderTreeBuilder(); GetRenderedBatch(renderTreeBuilder, oldTree, false); var oldComponent = GetComponents(oldTree).Single(); Assert.NotNull(oldComponent); @@ -360,6 +360,23 @@ namespace Microsoft.AspNetCore.Components.Test 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() { @@ -736,7 +753,7 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange oldTree.OpenComponent(123); oldTree.CloseComponent(); - using var initial = new RenderTreeBuilder(renderer); + using var initial = new RenderTreeBuilder(); GetRenderedBatch(initial, oldTree, false); // Assign initial IDs newTree.OpenComponent(123); newTree.CloseComponent(); @@ -835,9 +852,9 @@ namespace Microsoft.AspNetCore.Components.Test public void RecognizesAttributeEventHandlerValuesChanged() { // Arrange - Action retainedHandler = _ => { }; - Action removedHandler = _ => { }; - Action addedHandler = _ => { }; + Action retainedHandler = _ => { }; + Action removedHandler = _ => { }; + Action addedHandler = _ => { }; oldTree.OpenElement(0, "My element"); oldTree.AddAttribute(1, "onfoo", retainedHandler); oldTree.AddAttribute(2, "onbar", removedHandler); @@ -1553,7 +1570,7 @@ namespace Microsoft.AspNetCore.Components.Test newTree.CloseElement(); // using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + 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; @@ -1575,7 +1592,7 @@ namespace Microsoft.AspNetCore.Components.Test public void PreservesEventHandlerIdsForRetainedEventHandlers() { // Arrange - Action retainedHandler = _ => { }; + Action retainedHandler = _ => { }; oldTree.OpenElement(0, "My element"); oldTree.AddAttribute(1, "ontest", retainedHandler); oldTree.CloseElement(); @@ -1601,7 +1618,7 @@ namespace Microsoft.AspNetCore.Components.Test public void PreservesEventHandlerIdsForRetainedEventHandlers_SlowPath() { // Arrange - Action retainedHandler = _ => { }; + Action retainedHandler = _ => { }; oldTree.OpenElement(0, "My element"); oldTree.AddAttribute(0, "ontest", retainedHandler); oldTree.CloseElement(); @@ -1639,7 +1656,7 @@ namespace Microsoft.AspNetCore.Components.Test newTree.CloseComponent(); using var batchBuilder = new RenderBatchBuilder(); - using var renderTree = new RenderTreeBuilder(renderer); + using var renderTree = new RenderTreeBuilder(); RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTree.GetFrames(), oldTree.GetFrames()); var originalComponentInstance = (FakeComponent)oldTree.GetFrames().Array[0].Component; @@ -1679,7 +1696,7 @@ namespace Microsoft.AspNetCore.Components.Test } using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + 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); @@ -1709,7 +1726,7 @@ namespace Microsoft.AspNetCore.Components.Test } using var batchBuilder = new RenderBatchBuilder(); - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + 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); @@ -1735,7 +1752,7 @@ namespace Microsoft.AspNetCore.Components.Test newTree.CloseComponent(); // using var batchBuilder = new RenderBatchBuilder(); - using var renderTree = new RenderTreeBuilder(renderer); + using var renderTree = new RenderTreeBuilder(); RenderTreeDiffBuilder.ComputeDiff(renderer, batchBuilder, 0, renderTree.GetFrames(), oldTree.GetFrames()); // Act/Assert @@ -1750,9 +1767,9 @@ namespace Microsoft.AspNetCore.Components.Test public void AssignsDistinctIdToNewElementReferenceCaptures() { // Arrange - ElementRef ref1 = default, ref2 = default; - Action capture1 = val => { ref1 = val; }; - Action capture2 = val => { ref2 = val; }; + 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); @@ -1791,8 +1808,8 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange var refWriteCount = 0; - ElementRef ref1 = default; - Action capture1 = val => { ref1 = val; refWriteCount++; }; + ElementReference ref1 = default; + Action capture1 = val => { ref1 = val; refWriteCount++; }; oldTree.OpenElement(0, "My element"); oldTree.AddElementReferenceCapture(1, capture1); oldTree.CloseElement(); @@ -1945,7 +1962,7 @@ namespace Microsoft.AspNetCore.Components.Test oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Second param"); oldTree.CloseComponent(); - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + using var renderTreeBuilder = new RenderTreeBuilder(); GetRenderedBatch(renderTreeBuilder, oldTree, false); // Assign initial IDs var oldComponents = GetComponents(oldTree); @@ -2147,7 +2164,7 @@ namespace Microsoft.AspNetCore.Components.Test { if (initializeFromFrames) { - using var renderTreeBuilder = new RenderTreeBuilder(renderer); + using var renderTreeBuilder = new RenderTreeBuilder(); using var initializeBatchBuilder = new RenderBatchBuilder(); var emptyFrames = renderTreeBuilder.GetFrames(); @@ -2222,7 +2239,7 @@ namespace Microsoft.AspNetCore.Components.Test public string NonParameterProperty { get; set; } public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); return Task.CompletedTask; @@ -2235,7 +2252,7 @@ namespace Microsoft.AspNetCore.Components.Test { } - public Task SetParametersAsync(ParameterCollection parameters) => Task.CompletedTask; + public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; } private class CaptureSetParametersComponent : IComponent @@ -2246,7 +2263,7 @@ namespace Microsoft.AspNetCore.Components.Test { } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { SetParametersCallCount++; return Task.CompletedTask; @@ -2260,14 +2277,14 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterCollection parameters) => Task.CompletedTask; + public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; } private class NonDisposableComponent : IComponent { public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterCollection parameters) => Task.CompletedTask; + public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; } private static void AssertEdit( diff --git a/src/Components/Components/test/RenderTreeUpdaterTest.cs b/src/Components/Components/test/RenderTreeUpdaterTest.cs index 27d2699867..5011d6fb4a 100644 --- a/src/Components/Components/test/RenderTreeUpdaterTest.cs +++ b/src/Components/Components/test/RenderTreeUpdaterTest.cs @@ -17,9 +17,9 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var valuePropName = "testprop"; var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(renderer); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", () => { }); + builder.AddAttribute(1, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.AddAttribute(2, valuePropName, "initial value"); builder.CloseElement(); @@ -45,9 +45,9 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var valuePropName = "testprop"; var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(renderer); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", () => { }); + builder.AddAttribute(1, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.AddAttribute(2, valuePropName, "initial value"); builder.CloseElement(); @@ -70,14 +70,14 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var valuePropName = "testprop"; var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(renderer); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", () => { }); + builder.AddAttribute(1, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.AddAttribute(2, valuePropName, "unchanged 1"); builder.CloseElement(); builder.OpenElement(3, "elem"); - builder.AddAttribute(4, "eventname", () => { }); + builder.AddAttribute(4, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.AddAttribute(5, "unrelated prop before", "unchanged 2"); builder.AddAttribute(6, valuePropName, "initial value"); @@ -108,9 +108,9 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var valuePropName = "testprop"; var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(renderer); + var builder = new RenderTreeBuilder(); builder.OpenElement(0, "elem"); - builder.AddAttribute(1, "eventname", () => { }); + builder.AddAttribute(1, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.CloseElement(); var frames = builder.GetFrames(); @@ -133,13 +133,13 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var valuePropName = "testprop"; var renderer = new TestRenderer(); - var builder = new RenderTreeBuilder(renderer); + 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", () => { }); + builder.AddAttribute(4, "eventname", (Action)(() => { })); builder.SetUpdatesAttributeName(valuePropName); builder.CloseElement(); // elem with handler builder.CloseRegion(); diff --git a/src/Components/Components/test/RendererTest.cs b/src/Components/Components/test/RendererTest.cs index 9cccfafefb..f895c47f10 100644 --- a/src/Components/Components/test/RendererTest.cs +++ b/src/Components/Components/test/RendererTest.cs @@ -239,7 +239,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [EventActionsName] = new Dictionary> { @@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [EventActionsName] = new Dictionary> { @@ -327,7 +327,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [EventActionsName] = new Dictionary> { @@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); var log = new ConcurrentQueue<(int id, NestedAsyncComponent.EventType @event)>(); - await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [EventActionsName] = new Dictionary> { @@ -430,7 +430,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange: Render a component with an event handler var renderer = new TestRenderer(); - UIEventArgs receivedArgs = null; + EventArgs receivedArgs = null; var component = new EventComponent { @@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIEventArgs(); + var eventArgs = new EventArgs(); var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); // This should always be run synchronously @@ -456,11 +456,11 @@ namespace Microsoft.AspNetCore.Components.Test } [Fact] - public async Task CanDispatchEventsToTopLevelComponents() + public void CanDispatchEventsToTopLevelComponents() { // Arrange: Render a component with an event handler var renderer = new TestRenderer(); - UIEventArgs receivedArgs = null; + EventArgs receivedArgs = null; var component = new EventComponent { @@ -478,20 +478,50 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIEventArgs(); + var eventArgs = new EventArgs(); var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.True(renderTask.IsCompletedSuccessfully); Assert.Same(eventArgs, receivedArgs); - - await renderTask; // Does not throw } [Fact] - public async Task CanDispatchTypedEventsToTopLevelComponents() + 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(); - UIMouseEventArgs receivedArgs = null; + DerivedEventArgs receivedArgs = null; var component = new EventComponent { @@ -509,16 +539,14 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.True(renderTask.IsCompletedSuccessfully); Assert.Same(eventArgs, receivedArgs); - - await renderTask; // does not throw } [Fact] - public async Task CanDispatchActionEventsToTopLevelComponents() + public void CanDispatchActionEventsToTopLevelComponents() { // Arrange: Render a component with an event handler var renderer = new TestRenderer(); @@ -540,18 +568,16 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.True(renderTask.IsCompletedSuccessfully); Assert.NotNull(receivedArgs); - - await renderTask; // does not throw } [Fact] - public async Task CanDispatchEventsToNestedComponents() + public void CanDispatchEventsToNestedComponents() { - UIEventArgs receivedArgs = null; + EventArgs receivedArgs = null; // Arrange: Render parent component var renderer = new TestRenderer(); @@ -582,12 +608,10 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIEventArgs(); + var eventArgs = new EventArgs(); var renderTask = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.True(renderTask.IsCompletedSuccessfully); Assert.Same(eventArgs, receivedArgs); - - await renderTask; // does not throw } [Fact] @@ -595,7 +619,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange: Render a component with an event handler var renderer = new TestRenderer(); - UIEventArgs receivedArgs = null; + EventArgs receivedArgs = null; var state = 0; var tcs = new TaskCompletionSource(); @@ -622,7 +646,7 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIEventArgs(); + var eventArgs = new EventArgs(); var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.Equal(1, state); Assert.Same(eventArgs, receivedArgs); @@ -638,7 +662,7 @@ namespace Microsoft.AspNetCore.Components.Test { // Arrange: Render a component with an event handler var renderer = new TestRenderer(); - UIMouseEventArgs receivedArgs = null; + DerivedEventArgs receivedArgs = null; var state = 0; var tcs = new TaskCompletionSource(); @@ -665,7 +689,7 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.Equal(1, state); Assert.Same(eventArgs, receivedArgs); @@ -708,7 +732,7 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.Equal(1, state); Assert.NotNull(receivedArgs); @@ -722,7 +746,7 @@ namespace Microsoft.AspNetCore.Components.Test [Fact] public async Task CanAsyncDispatchEventsToNestedComponents() { - UIEventArgs receivedArgs = null; + EventArgs receivedArgs = null; var state = 0; var tcs = new TaskCompletionSource(); @@ -762,7 +786,7 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Null(receivedArgs); // Act/Assert: Event can be fired - var eventArgs = new UIEventArgs(); + var eventArgs = new EventArgs(); var task = renderer.DispatchEventAsync(eventHandlerId, eventArgs); Assert.Equal(1, state); Assert.Same(eventArgs, receivedArgs); @@ -790,7 +814,7 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), parentComponent.SomeMethod); + builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)parentComponent.SomeMethod); builder.CloseComponent(); }; parentComponent.OnEvent = () => @@ -807,7 +831,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -831,10 +855,10 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), () => + builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => { parentComponent.SomeMethod(); - }); + })); builder.CloseComponent(); }; parentComponent.OnEvent = () => @@ -851,7 +875,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -890,7 +914,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -931,7 +955,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -973,7 +997,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -992,7 +1016,7 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)parentComponent.SomeMethod)); + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)parentComponent.SomeMethod)); builder.CloseComponent(); }; parentComponent.OnEvent = () => @@ -1009,7 +1033,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -1030,7 +1054,7 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)(() => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)(() => { parentComponent.SomeMethod(); }))); @@ -1050,7 +1074,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -1071,7 +1095,7 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Func)(() => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Func)(() => { parentComponent.SomeMethod(); return Task.CompletedTask; @@ -1092,7 +1116,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var eventArgs = new UIMouseEventArgs(); + var eventArgs = new DerivedEventArgs(); await renderer.DispatchEventAsync(eventHandlerId, eventArgs); // Assert @@ -1109,10 +1133,10 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAction), () => + builder.AddAttribute(1, nameof(EventComponent.OnClickAction), (Action)(() => { // Do nothing. - }); + })); builder.CloseComponent(); }; @@ -1125,7 +1149,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.RanToCompletion, task.Status); @@ -1157,7 +1181,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.RanToCompletion, task.Status); @@ -1168,14 +1192,14 @@ namespace Microsoft.AspNetCore.Components.Test public async Task DispatchEventAsync_EventCallbackOfT_SynchronousCompletion() { // Arrange - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => { arg = e; }))); @@ -1191,7 +1215,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1224,7 +1248,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.Canceled, task.Status); @@ -1256,7 +1280,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.Canceled, task.Status); @@ -1267,14 +1291,14 @@ namespace Microsoft.AspNetCore.Components.Test public async Task DispatchEventAsync_EventCallbackOfT_SynchronousCancellation() { // Arrange - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => { arg = e; throw new OperationCanceledException(); @@ -1291,7 +1315,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1324,7 +1348,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.Faulted, task.Status); @@ -1356,7 +1380,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.Faulted, task.Status); @@ -1367,14 +1391,14 @@ namespace Microsoft.AspNetCore.Components.Test public async Task DispatchEventAsync_EventCallbackOfT_SynchronousException() { // Arrange - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, (Action)((e) => { arg = e; throw new InvalidTimeZoneException(); @@ -1391,7 +1415,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1410,10 +1434,10 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), async () => + builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => { await tcs.Task; - }); + })); builder.CloseComponent(); }; @@ -1426,7 +1450,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1461,7 +1485,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1475,14 +1499,14 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var tcs = new TaskCompletionSource(); - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => { arg = e; await tcs.Task; @@ -1499,7 +1523,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1519,11 +1543,11 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), async () => + builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => { await tcs.Task; throw new TaskCanceledException(); - }); + })); builder.CloseComponent(); }; @@ -1536,7 +1560,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1574,7 +1598,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1590,14 +1614,14 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var tcs = new TaskCompletionSource(); - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => { arg = e; await tcs.Task; @@ -1615,7 +1639,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1637,11 +1661,11 @@ namespace Microsoft.AspNetCore.Components.Test parentComponent.RenderFragment = (builder) => { builder.OpenComponent(0); - builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), async () => + builder.AddAttribute(1, nameof(EventComponent.OnClickAsyncAction), (Func)(async () => { await tcs.Task; throw new InvalidTimeZoneException(); - }); + })); builder.CloseComponent(); }; @@ -1654,7 +1678,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1691,7 +1715,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.Equal(TaskStatus.WaitingForActivation, task.Status); @@ -1706,14 +1730,14 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var tcs = new TaskCompletionSource(); - UIMouseEventArgs arg = null; + 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) => + builder.AddAttribute(1, nameof(EventComponent.OnClickEventCallbackOfT), EventCallback.Factory.Create(parentComponent, async (e) => { arg = e; await tcs.Task; @@ -1731,7 +1755,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act - var task = renderer.DispatchEventAsync(eventHandlerId, new UIMouseEventArgs()); + var task = renderer.DispatchEventAsync(eventHandlerId, new DerivedEventArgs()); // Assert Assert.NotNull(arg); @@ -1750,7 +1774,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert await Assert.ThrowsAsync(() => { - return renderer.DispatchEventAsync(0, new UIEventArgs()); + return renderer.DispatchEventAsync(0, new EventArgs()); }); } @@ -2028,7 +2052,7 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var renderer = new TestRenderer(); var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; + Action origEventHandler = args => { eventCount++; }; var component = new EventComponent { OnTest = origEventHandler }; var componentId = renderer.AssignRootComponentId(component); component.TriggerRender(); @@ -2070,7 +2094,7 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var renderer = new TestRenderer(); var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; + Action origEventHandler = args => { eventCount++; }; var component = new EventComponent { OnTest = origEventHandler }; var componentId = renderer.AssignRootComponentId(component); component.TriggerRender(); @@ -2105,7 +2129,7 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var renderer = new TestRenderer(); var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; + Action origEventHandler = args => { eventCount++; }; var component = new ConditionalParentComponent { IncludeChild = true, @@ -2156,7 +2180,7 @@ namespace Microsoft.AspNetCore.Components.Test // Arrange var renderer = new TestRenderer(); var eventCount = 0; - Action origEventHandler = args => { eventCount++; }; + Action origEventHandler = args => { eventCount++; }; var component = new EventComponent { OnTest = origEventHandler }; var componentId = renderer.AssignRootComponentId(component); component.TriggerRender(); @@ -2198,7 +2222,7 @@ namespace Microsoft.AspNetCore.Components.Test { builder.AddContent(0, "Child event count: " + eventCount); builder.OpenComponent(1); - builder.AddAttribute(2, nameof(EventComponent.OnTest), new Action(args => + builder.AddAttribute(2, nameof(EventComponent.OnTest), new Action(args => { eventCount++; rootComponent.TriggerRender(); @@ -2444,7 +2468,7 @@ namespace Microsoft.AspNetCore.Components.Test .AttributeEventHandlerId; // Act: Toggle the checkbox - var eventArgs = new UIChangeEventArgs { Value = true }; + var eventArgs = new ChangeEventArgs { Value = true }; var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs); Assert.True(renderTask.IsCompletedSuccessfully); @@ -2689,7 +2713,7 @@ namespace Microsoft.AspNetCore.Components.Test }; var numEventsFired = 0; EventComponent component = null; - Action eventHandler = null; + Action eventHandler = null; eventHandler = _ => { @@ -2713,14 +2737,14 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert 1: Event can be fired for the first time var render1TCS = new TaskCompletionSource(); renderer.NextUpdateDisplayReturnTask = render1TCS.Task; - await renderer.DispatchEventAsync(eventHandlerId, new UIEventArgs()); + 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 UIEventArgs()); + await renderer.DispatchEventAsync(eventHandlerId, new EventArgs()); Assert.Equal(2, numEventsFired); // Act/Assert 3: After we complete the first UI update in which a given @@ -2736,7 +2760,7 @@ namespace Microsoft.AspNetCore.Components.Test await awaitableTask; var ex = await Assert.ThrowsAsync(() => { - return renderer.DispatchEventAsync(eventHandlerId, new UIEventArgs()); + return renderer.DispatchEventAsync(eventHandlerId, new EventArgs()); }); Assert.Equal($"There is no event handler with ID {eventHandlerId}", ex.Message); Assert.Equal(2, numEventsFired); @@ -2752,7 +2776,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var task = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var task = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -2785,7 +2809,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -2818,7 +2842,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -2852,7 +2876,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -2933,7 +2957,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -2991,7 +3015,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -3046,7 +3070,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -3100,7 +3124,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -3134,7 +3158,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + var renderTask = renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -3171,7 +3195,7 @@ namespace Microsoft.AspNetCore.Components.Test // Act/Assert var componentId = renderer.AssignRootComponentId(component); - await renderer.RenderRootComponentAsync(componentId, ParameterCollection.FromDictionary(new Dictionary + await renderer.RenderRootComponentAsync(componentId, ParameterView.FromDictionary(new Dictionary { [nameof(NestedAsyncComponent.EventActions)] = new Dictionary> { @@ -3294,7 +3318,7 @@ namespace Microsoft.AspNetCore.Components.Test FieldValue = "new property value", ComponentId = componentId }; - var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, eventFieldInfo, new UIChangeEventArgs + var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, eventFieldInfo, new ChangeEventArgs { Value = "new property value" }); @@ -3312,7 +3336,7 @@ namespace Microsoft.AspNetCore.Components.Test // 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)); + AssertFrame.Attribute(attributeFrame, "ontestevent", typeof(Action)); Assert.NotEqual(default, attributeFrame.AttributeEventHandlerId); Assert.NotEqual(eventHandlerId, attributeFrame.AttributeEventHandlerId); }); @@ -3346,7 +3370,7 @@ namespace Microsoft.AspNetCore.Components.Test ComponentId = componentId, FieldValue = newPropertyValue, }; - var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, fieldInfo, new UIChangeEventArgs + var dispatchEventTask = renderer.DispatchEventAsync(eventHandlerId, fieldInfo, new ChangeEventArgs { Value = newPropertyValue }); @@ -3364,7 +3388,7 @@ namespace Microsoft.AspNetCore.Components.Test // 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)); + AssertFrame.Attribute(attributeFrame, "ontestevent", typeof(Action)); Assert.NotEqual(default, attributeFrame.AttributeEventHandlerId); Assert.NotEqual(eventHandlerId, attributeFrame.AttributeEventHandlerId); }); @@ -3404,7 +3428,7 @@ namespace Microsoft.AspNetCore.Components.Test _renderHandle = renderHandle; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { TriggerRender(); return Task.CompletedTask; @@ -3473,7 +3497,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => RenderHandle = renderHandle; - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); return Task.CompletedTask; @@ -3483,16 +3507,16 @@ namespace Microsoft.AspNetCore.Components.Test private class EventComponent : AutoRenderComponent, IComponent, IHandleEvent { [Parameter] - public Action OnTest { get; set; } + public Action OnTest { get; set; } [Parameter] - public Func OnTestAsync { get; set; } + public Func OnTestAsync { get; set; } [Parameter] - public Action OnClick { get; set; } + public Action OnClick { get; set; } [Parameter] - public Func OnClickAsync { get; set; } + public Func OnClickAsync { get; set; } [Parameter] public Action OnClickAction { get; set; } @@ -3504,7 +3528,7 @@ namespace Microsoft.AspNetCore.Components.Test public EventCallback OnClickEventCallback { get; set; } [Parameter] - public EventCallback OnClickEventCallbackOfT { get; set; } + public EventCallback OnClickEventCallbackOfT { get; set; } public bool SkipElement { get; set; } private int renderCount = 0; @@ -3622,7 +3646,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => _renderHandle = renderHandle; - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); Render(); @@ -3640,7 +3664,7 @@ namespace Microsoft.AspNetCore.Components.Test => _renderHandle.Render(builder => { builder.OpenElement(0, "my button"); - builder.AddAttribute(1, "my click handler", new Action(eventArgs => OnClick(eventArgs))); + builder.AddAttribute(1, "my click handler", new Action(eventArgs => OnClick(eventArgs))); builder.CloseElement(); }); } @@ -3653,7 +3677,7 @@ namespace Microsoft.AspNetCore.Components.Test public void Attach(RenderHandle renderHandle) => _renderHandles.Add(renderHandle); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { return Task.CompletedTask; } @@ -3686,11 +3710,11 @@ namespace Microsoft.AspNetCore.Components.Test { builder.OpenElement(0, "input"); builder.AddAttribute(1, "type", "checkbox"); - builder.AddAttribute(2, "value", BindMethods.GetValue(CheckboxEnabled)); + 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", BindMethods.GetValue(SomeStringProperty)); + 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(); @@ -3710,7 +3734,7 @@ namespace Microsoft.AspNetCore.Components.Test return Task.CompletedTask; } - Task IComponent.SetParametersAsync(ParameterCollection parameters) + Task IComponent.SetParametersAsync(ParameterView parameters) { TriggerRender(); return Task.CompletedTask; @@ -3769,7 +3793,7 @@ namespace Microsoft.AspNetCore.Components.Test _renderHandler = renderHandle; } - public async Task SetParametersAsync(ParameterCollection parameters) + public async Task SetParametersAsync(ParameterView parameters) { int n; while (Number > 0) @@ -3818,7 +3842,7 @@ namespace Microsoft.AspNetCore.Components.Test return task; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { return TriggerRenderAsync(); } @@ -4071,7 +4095,7 @@ namespace Microsoft.AspNetCore.Components.Test builder.OpenElement(0, "element with event"); builder.AddAttribute(1, nameof(BoundString), BoundString); - builder.AddAttribute(2, "ontestevent", new Action((UIChangeEventArgs eventArgs) => + builder.AddAttribute(2, "ontestevent", new Action((ChangeEventArgs eventArgs) => { BoundString = (string)eventArgs.Value; TriggerRender(); @@ -4081,5 +4105,9 @@ namespace Microsoft.AspNetCore.Components.Test builder.CloseElement(); } } + + private class DerivedEventArgs : EventArgs + { + } } } diff --git a/src/Components/Components/test/Rendering/HtmlRendererTestBase.cs b/src/Components/Components/test/Rendering/HtmlRendererTestBase.cs index 1650158ee7..d12aaf32ad 100644 --- a/src/Components/Components/test/Rendering/HtmlRendererTestBase.cs +++ b/src/Components/Components/test/Rendering/HtmlRendererTestBase.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -72,7 +72,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -172,7 +172,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -193,7 +193,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -237,7 +237,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -267,7 +267,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -326,7 +326,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -339,26 +339,26 @@ namespace Microsoft.AspNetCore.Components.Rendering var expectedHtml = new[] { "<", "p", ">", "<", "input", " ", "value", "=", "\"", "5", "\"", " />", "" }; - RenderFragment Content(ParameterCollection pc) => new RenderFragment((RenderTreeBuilder rtb) => + RenderFragment Content(ParameterView pc) => new RenderFragment((RenderTreeBuilder rtb) => { rtb.OpenElement(0, "p"); rtb.OpenElement(1, "input"); - rtb.AddAttribute(2, "change", pc.GetValueOrDefault>("update")); + rtb.AddAttribute(2, "change", pc.GetValueOrDefault>("update")); rtb.AddAttribute(3, "value", pc.GetValueOrDefault("value")); rtb.CloseElement(); rtb.CloseElement(); }); var serviceProvider = new ServiceCollection() - .AddSingleton(new Func(Content)) + .AddSingleton(new Func(Content)) .BuildServiceProvider(); var htmlRenderer = GetHtmlRenderer(serviceProvider); - Action change = (UIChangeEventArgs changeArgs) => throw new InvalidOperationException(); + Action change = (ChangeEventArgs changeArgs) => throw new InvalidOperationException(); // Act var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync( - new ParameterCollection(new[] { + new ParameterView(new[] { RenderTreeFrame.Element(0,string.Empty), RenderTreeFrame.Attribute(1,"update",change), RenderTreeFrame.Attribute(2,"value",5) @@ -388,7 +388,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -415,7 +415,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.Empty))); + var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.Empty))); // Assert Assert.Equal(expectedHtml, result); @@ -445,9 +445,9 @@ namespace Microsoft.AspNetCore.Components.Rendering } [Inject] - Func CreateRenderFragment { get; set; } + Func CreateRenderFragment { get; set; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { RenderHandle.Render(CreateRenderFragment(parameters)); return Task.CompletedTask; @@ -465,7 +465,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = await htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.FromDictionary(new Dictionary + var result = await htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.FromDictionary(new Dictionary { ["Value"] = 10 }))); @@ -489,7 +489,7 @@ namespace Microsoft.AspNetCore.Components.Rendering var htmlRenderer = GetHtmlRenderer(serviceProvider); // Act - var result = await htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterCollection.FromDictionary(new Dictionary + var result = await htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync(ParameterView.FromDictionary(new Dictionary { ["Nested"] = false, ["Value"] = 10 @@ -558,13 +558,13 @@ namespace Microsoft.AspNetCore.Components.Rendering _renderHandle = renderHandle; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { _renderHandle.Render(CreateRenderFragment(parameters)); return Task.CompletedTask; } - private RenderFragment CreateRenderFragment(ParameterCollection parameters) + private RenderFragment CreateRenderFragment(ParameterView parameters) { return RenderFragment; @@ -589,7 +589,7 @@ namespace Microsoft.AspNetCore.Components.Rendering _renderHandle = renderHandle; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { _renderHandle.Render(Fragment); return Task.CompletedTask; diff --git a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs b/src/Components/Components/test/Routing/RouteTableFactoryTests.cs index f6733d8ceb..8250fab16b 100644 --- a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs +++ b/src/Components/Components/test/Routing/RouteTableFactoryTests.cs @@ -268,8 +268,9 @@ namespace Microsoft.AspNetCore.Components.Test.Routing { // Arrange var routeTable = new TestRouteTableBuilder() - .AddRoute("/an/awesome/path") - .AddRoute("/{some}/awesome/{route}/").Build(); + .AddRoute("/an/awesome/path", typeof(TestHandler1)) + .AddRoute("/{some}/awesome/{route}/", typeof(TestHandler2)) + .Build(); var context = new RouteContext("/an/awesome/path"); // Act @@ -346,9 +347,58 @@ namespace Microsoft.AspNetCore.Components.Test.Routing 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, Type)> _routeTemplates = new List<(string, Type)>(); + IList<(string Template, Type Handler)> _routeTemplates = new List<(string, Type)>(); Type _handler = typeof(object); public TestRouteTableBuilder AddRoute(string template, Type handler = null) @@ -361,10 +411,10 @@ namespace Microsoft.AspNetCore.Components.Test.Routing { try { - return new RouteTable(_routeTemplates - .Select(rt => new RouteEntry(TemplateParser.ParseTemplate(rt.Item1), rt.Item2)) - .OrderBy(id => id, RouteTableFactory.RoutePrecedence) - .ToArray()); + 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) { @@ -373,5 +423,8 @@ namespace Microsoft.AspNetCore.Components.Test.Routing } } } + + class TestHandler1 { } + class TestHandler2 { } } } diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf index 709df54396..694b1b7f13 100644 --- a/src/Components/ComponentsNoDeps.slnf +++ b/src/Components/ComponentsNoDeps.slnf @@ -9,6 +9,8 @@ "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\\Server\\src\\Microsoft.AspNetCore.Blazor.Server.csproj", "Blazor\\Templates\\src\\Microsoft.AspNetCore.Blazor.Templates.csproj", "Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", @@ -18,6 +20,7 @@ "Blazor\\testassets\\MonoSanity\\MonoSanity.csproj", "Blazor\\testassets\\StandaloneApp\\StandaloneApp.csproj", "Web\\src\\Microsoft.AspNetCore.Components.Web.csproj", + "Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj", "Components\\perf\\Microsoft.AspNetCore.Components.Performance.csproj", "Components\\src\\Microsoft.AspNetCore.Components.csproj", "Components\\test\\Microsoft.AspNetCore.Components.Tests.csproj", diff --git a/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.csproj b/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.csproj index e27f07cc33..491c5b8cff 100644 --- a/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.csproj +++ b/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.csproj @@ -7,11 +7,11 @@ - + diff --git a/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.netcoreapp3.0.cs b/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.netcoreapp3.0.cs index e39c5d64ac..7a89318f43 100644 --- a/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.netcoreapp3.0.cs +++ b/src/Components/Server/ref/Microsoft.AspNetCore.Components.Server.netcoreapp3.0.cs @@ -14,8 +14,6 @@ namespace Microsoft.AspNetCore.Builder } public static partial class ComponentEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) { throw null; } - public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Action configureOptions) { throw null; } public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type type, string selector) { throw null; } public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type type, string selector, System.Action configureOptions) { throw null; } public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type componentType, string selector, string path) { throw null; } @@ -28,29 +26,13 @@ namespace Microsoft.AspNetCore.Builder } namespace Microsoft.AspNetCore.Components.Server { - public partial class CircuitOptions + public sealed partial class CircuitOptions { public CircuitOptions() { } + public bool DetailedErrors { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public int DisconnectedCircuitMaxRetained { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.TimeSpan DisconnectedCircuitRetentionPeriod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.TimeSpan JSInteropDefaultCallTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public bool JSInteropDetailedErrors { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public int MaxRetainedDisconnectedCircuits { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public partial class ComponentPrerenderingContext - { - public ComponentPrerenderingContext() { } - public System.Type ComponentType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Http.HttpContext Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public Microsoft.AspNetCore.Components.ParameterCollection Parameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - } - public sealed partial class ComponentPrerenderResult - { - internal ComponentPrerenderResult() { } - public void WriteTo(System.IO.TextWriter writer) { } - } - public partial interface IComponentPrerenderer - { - System.Threading.Tasks.Task PrerenderComponentAsync(Microsoft.AspNetCore.Components.Server.ComponentPrerenderingContext context); } } namespace Microsoft.AspNetCore.Components.Server.Circuits @@ -70,13 +52,6 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public virtual System.Threading.Tasks.Task OnConnectionUpAsync(Microsoft.AspNetCore.Components.Server.Circuits.Circuit circuit, System.Threading.CancellationToken cancellationToken) { throw null; } } } -namespace Microsoft.AspNetCore.Components.Web.Rendering -{ - public partial class RemoteRendererException : System.Exception - { - public RemoteRendererException(string message) { } - } -} namespace Microsoft.Extensions.DependencyInjection { public static partial class ComponentServiceCollectionExtensions diff --git a/src/Components/Server/src/BlazorPack/BlazorPackHubProtocol.cs b/src/Components/Server/src/BlazorPack/BlazorPackHubProtocol.cs index ea97e65cdc..32034b556e 100644 --- a/src/Components/Server/src/BlazorPack/BlazorPackHubProtocol.cs +++ b/src/Components/Server/src/BlazorPack/BlazorPackHubProtocol.cs @@ -424,12 +424,8 @@ namespace Microsoft.AspNetCore.Components.Server.BlazorPack writer.Write(floatValue); break; - case byte[] byteArray: - writer.Write(byteArray); - break; - - case Exception exception: - writer.Write(exception.ToString()); + case ArraySegment bytes: + writer.Write(bytes); break; default: @@ -461,13 +457,6 @@ namespace Microsoft.AspNetCore.Components.Server.BlazorPack { return reader.ReadSingle(); } - else if (type == typeof(byte[])) - { - var bytes = reader.ReadBytes(); - // MessagePack ensures there are at least as many bytes in the message as declared by the byte header. - // Consequently it is safe to do ToArray on the returned SequenceReader instance. - return bytes.ToArray(); - } } catch (Exception ex) { diff --git a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs index 4248dae1d7..8af4ad37e8 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs @@ -15,42 +15,6 @@ namespace Microsoft.AspNetCore.Builder /// public static class ComponentEndpointRouteBuilderExtensions { - /// - /// Maps the Blazor to the default path. - /// - /// The . - /// The . - public static ComponentEndpointConventionBuilder MapBlazorHub(this IEndpointRouteBuilder endpoints) - { - if (endpoints == null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - return endpoints.MapBlazorHub(configureOptions: _ => { }); - } - - /// - /// Maps the Blazor to the default path. - /// - /// The . - /// A callback to configure dispatcher options. - /// The . - public static ComponentEndpointConventionBuilder MapBlazorHub(this IEndpointRouteBuilder endpoints, Action configureOptions) - { - if (endpoints == null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - if (configureOptions == null) - { - throw new ArgumentNullException(nameof(configureOptions)); - } - - return new ComponentEndpointConventionBuilder(endpoints.MapHub(ComponentHub.DefaultPath, configureOptions)); - } - /// ///Maps the Blazor to the default path and associates /// the component to this hub instance as the given DOM . diff --git a/src/Components/Server/src/CircuitOptions.cs b/src/Components/Server/src/CircuitOptions.cs index 5e1dcd371f..30c1b9c407 100644 --- a/src/Components/Server/src/CircuitOptions.cs +++ b/src/Components/Server/src/CircuitOptions.cs @@ -6,9 +6,9 @@ using System; namespace Microsoft.AspNetCore.Components.Server { /// - /// Options to configure ASP.NET Core Components. + /// Options to configure circuit handler for server-side Blazor /// - public class CircuitOptions + public sealed class CircuitOptions { /// /// Gets or sets a value that determines the maximum number of disconnected circuit state details @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Server /// /// Defaults to 100. /// - public int MaxRetainedDisconnectedCircuits { get; set; } = 100; + public int DisconnectedCircuitMaxRetained { get; set; } = 100; /// /// Gets or sets a value that determines the maximum duration state for a disconnected circuit is @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Components.Server /// /// /// This value determines the maximium duration circuit state is retained by the server before being evicted. - /// + /// /// /// /// @@ -47,15 +47,15 @@ namespace Microsoft.AspNetCore.Components.Server public TimeSpan DisconnectedCircuitRetentionPeriod { get; set; } = TimeSpan.FromMinutes(3); /// - /// Gets or sets a value that determines whether or not to send detailed exception messages from .NET interop method invocation - /// exceptions to JavaScript. + /// Gets or sets a value that determines whether or not to send detailed exception messages to JavaScript when an unhandled exception + /// happens on the circuit or when a .NET method invocation through JS interop results in an exception. /// /// /// This value should only be turned on in development scenarios as turning it on in production might result in the leak of /// sensitive information to untrusted parties. /// /// Defaults to false. - public bool JSInteropDetailedErrors { get; set; } + public bool DetailedErrors { get; set; } /// /// Gets or sets a value that indicates how long the server will wait before timing out an asynchronous JavaScript function invocation. diff --git a/src/Components/Server/src/Circuits/ArrayBuilderMemoryStream.cs b/src/Components/Server/src/Circuits/ArrayBuilderMemoryStream.cs new file mode 100644 index 0000000000..ff1ff63114 --- /dev/null +++ b/src/Components/Server/src/Circuits/ArrayBuilderMemoryStream.cs @@ -0,0 +1,125 @@ +// Copyright (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.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Components.Web.Rendering +{ + /// + /// Writeable memory stream backed by a an . + /// + internal sealed class ArrayBuilderMemoryStream : Stream + { + public ArrayBuilderMemoryStream(ArrayBuilder arrayBuilder) + { + ArrayBuilder = arrayBuilder; + } + + /// + public override bool CanRead => false; + + /// + public override bool CanSeek => false; + + /// + public override bool CanWrite => true; + + /// + public override long Length => ArrayBuilder.Count; + + /// + public override long Position + { + get => ArrayBuilder.Count; + set => throw new NotSupportedException(); + } + + public ArrayBuilder ArrayBuilder { get; } + + /// + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + + /// + public override int Read(byte[] buffer, int offset, int count) + => throw new NotSupportedException(); + + /// + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + => throw new NotSupportedException(); + + /// + public override void Write(byte[] buffer, int offset, int count) + { + ValidateArguments(buffer, offset, count); + + ArrayBuilder.Append(buffer, offset, count); + } + + /// + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ValidateArguments(buffer, offset, count); + + ArrayBuilder.Append(buffer, offset, count); + return Task.CompletedTask; + } + + /// + public override void Flush() + { + // Do nothing. + } + + /// + public override Task FlushAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + /// + public override void SetLength(long value) => throw new NotSupportedException(); + + /// + protected override void Dispose(bool disposing) + { + // Do nothing. + } + + /// + public override ValueTask DisposeAsync() => default; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void ValidateArguments(byte[] buffer, int offset, int count) + { + if (buffer == null) + { + ThrowHelper.ThrowArgumentNullException(nameof(buffer)); + } + + if (offset < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(nameof(offset)); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(nameof(count)); + } + + if (buffer.Length - offset < count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(nameof(offset)); + } + } + + private static class ThrowHelper + { + public static void ThrowArgumentNullException(string name) + => throw new ArgumentNullException(name); + + public static void ThrowArgumentOutOfRangeException(string name) + => throw new ArgumentOutOfRangeException(name); + } + } +} diff --git a/src/Components/Server/src/Circuits/CircuitFactory.cs b/src/Components/Server/src/Circuits/CircuitFactory.cs index 99012a31c8..c91545d131 100644 --- a/src/Components/Server/src/Circuits/CircuitFactory.cs +++ b/src/Components/Server/src/Circuits/CircuitFactory.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.Security.Claims; using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Components.Server.Circuits @@ -10,7 +11,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public abstract CircuitHost CreateCircuitHost( HttpContext httpContext, CircuitClientProxy client, - string uriAbsolute, - string baseUriAbsolute); + string baseUri, + string uri, + ClaimsPrincipal user); } } diff --git a/src/Components/Server/src/Circuits/CircuitHost.cs b/src/Components/Server/src/Circuits/CircuitHost.cs index 65ea20fc6b..563cacbff6 100644 --- a/src/Components/Server/src/Circuits/CircuitHost.cs +++ b/src/Components/Server/src/Circuits/CircuitHost.cs @@ -3,12 +3,12 @@ using System; using System.Collections.Generic; +using System.Security.Claims; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web.Rendering; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.JSInterop; @@ -17,31 +17,28 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits { internal class CircuitHost : IAsyncDisposable { - private static readonly AsyncLocal _current = new AsyncLocal(); private readonly SemaphoreSlim HandlerLock = new SemaphoreSlim(1); private readonly IServiceScope _scope; private readonly CircuitHandler[] _circuitHandlers; private readonly ILogger _logger; private bool _initialized; - /// - /// Gets the current , if any. - /// - public static CircuitHost Current => _current.Value; - /// /// Sets the current . /// /// The . /// - /// Calling will store the circuit - /// and other related values such as the and + /// Calling will store related values such as the + /// and /// in the local execution context. Application code should not need to call this method, /// it is primarily used by the Server-Side Components infrastructure. /// public static void SetCurrentCircuitHost(CircuitHost circuitHost) { - _current.Value = circuitHost ?? throw new ArgumentNullException(nameof(circuitHost)); + if (circuitHost is null) + { + throw new ArgumentNullException(nameof(circuitHost)); + } JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime); RendererRegistry.SetCurrentRendererRegistry(circuitHost.RendererRegistry); @@ -55,7 +52,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, - IList descriptors, + IReadOnlyList descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger) @@ -90,41 +87,17 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public RendererRegistry RendererRegistry { get; } - public IList Descriptors { get; } + public IReadOnlyList Descriptors { get; } public IServiceProvider Services { get; } - public Task PrerenderComponentAsync(Type componentType, ParameterCollection parameters) + public void SetCircuitUser(ClaimsPrincipal user) { - return Renderer.Dispatcher.InvokeAsync(async () => + var authenticationStateProvider = Services.GetService() as IHostEnvironmentAuthenticationStateProvider; + if (authenticationStateProvider != null) { - var result = await Renderer.RenderComponentAsync(componentType, parameters); - - // When we prerender we start the circuit in a disconnected state. As such, we only call - // OnCircuitOpenenedAsync here and when the client reconnects we run OnConnectionUpAsync - await OnCircuitOpenedAsync(CancellationToken.None); - - return result; - }); - } - - internal void InitializeCircuitAfterPrerender(UnhandledExceptionEventHandler unhandledException) - { - if (!_initialized) - { - _initialized = true; - UnhandledException += unhandledException; - var uriHelper = (RemoteUriHelper)Services.GetRequiredService(); - if (!uriHelper.HasAttachedJSRuntime) - { - uriHelper.AttachJsRuntime(JSRuntime); - } - - var navigationInterception = (RemoteNavigationInterception)Services.GetRequiredService(); - if (!navigationInterception.HasAttachedJSRuntime) - { - navigationInterception.AttachJSRuntime(JSRuntime); - } + var authenticationState = new AuthenticationState(user); + authenticationStateProvider.SetAuthenticationState(Task.FromResult(authenticationState)); } } @@ -133,7 +106,75 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits // Dispatch any buffered renders we accumulated during a disconnect. // Note that while the rendering is async, we cannot await it here. The Task returned by ProcessBufferedRenderBatches relies on // OnRenderCompleted to be invoked to complete, and SignalR does not allow concurrent hub method invocations. - var _ = Renderer.Dispatcher.InvokeAsync(() => Renderer.ProcessBufferedRenderBatches()); + _ = Renderer.Dispatcher.InvokeAsync(() => Renderer.ProcessBufferedRenderBatches()); + } + + public async Task EndInvokeJSFromDotNet(long asyncCall, bool succeded, string arguments) + { + try + { + AssertInitialized(); + + await Renderer.Dispatcher.InvokeAsync(() => + { + SetCurrentCircuitHost(this); + if (!succeded) + { + // We can log the arguments here because it is simply the JS error with the call stack. + Log.EndInvokeJSFailed(_logger, asyncCall, arguments); + } + else + { + Log.EndInvokeJSSucceeded(_logger, asyncCall); + } + + DotNetDispatcher.EndInvoke(arguments); + }); + } + catch (Exception ex) + { + Log.EndInvokeDispatchException(_logger, ex); + } + } + + public async Task DispatchEvent(string eventDescriptorJson, string eventArgs) + { + RendererRegistryEventDispatcher.BrowserEventDescriptor eventDescriptor = null; + try + { + AssertInitialized(); + eventDescriptor = ParseEventDescriptor(eventDescriptorJson); + if (eventDescriptor == null) + { + return; + } + + await Renderer.Dispatcher.InvokeAsync(() => + { + SetCurrentCircuitHost(this); + return RendererRegistryEventDispatcher.DispatchEvent(eventDescriptor, eventArgs); + }); + } + catch (Exception ex) + { + Log.DispatchEventFailedToDispatchEvent(_logger, eventDescriptor != null ? eventDescriptor.EventHandlerId.ToString() : null, ex); + UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); + } + } + + private RendererRegistryEventDispatcher.BrowserEventDescriptor ParseEventDescriptor(string eventDescriptorJson) + { + try + { + return JsonSerializer.Deserialize( + eventDescriptorJson, + JsonSerializerOptionsProvider.Options); + } + catch (Exception ex) + { + Log.DispatchEventFailedToParseEventDescriptor(_logger, ex); + return null; + } } public async Task InitializeAsync(CancellationToken cancellationToken) @@ -152,13 +193,11 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits // That's because AddComponentAsync waits for quiescence, which can take // arbitrarily long. In the meantime we might need to be receiving and // processing incoming JSInterop calls or similar. - for (var i = 0; i < Descriptors.Count; i++) + var count = Descriptors.Count; + for (var i = 0; i < count; i++) { - var (componentType, domElementSelector, prerendered) = Descriptors[i]; - if (!prerendered) - { - await Renderer.AddComponentAsync(componentType, domElementSelector); - } + var (componentType, domElementSelector) = Descriptors[i]; + await Renderer.AddComponentAsync(componentType, domElementSelector); } } catch (Exception ex) @@ -170,20 +209,58 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits }); } - public async void BeginInvokeDotNetFromJS(string callId, string assemblyName, string methodIdentifier, long dotNetObjectId, string argsJson) + public async Task BeginInvokeDotNetFromJS(string callId, string assemblyName, string methodIdentifier, long dotNetObjectId, string argsJson) { - AssertInitialized(); - try { + AssertInitialized(); + if (assemblyName == "Microsoft.AspNetCore.Components.Web" && methodIdentifier == "DispatchEvent") + { + Log.DispatchEventTroughJSInterop(_logger); + return; + } + await Renderer.Dispatcher.InvokeAsync(() => { SetCurrentCircuitHost(this); + Log.BeginInvokeDotNet(_logger, callId, assemblyName, methodIdentifier, dotNetObjectId); DotNetDispatcher.BeginInvoke(callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson); }); } catch (Exception ex) { + // We don't expect any of this code to actually throw, because DotNetDispatcher.BeginInvoke doesn't throw + // however, we still want this to get logged if we do. + UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); + } + } + + public async Task OnLocationChangedAsync(string uri, bool intercepted) + { + try + { + AssertInitialized(); + await Renderer.Dispatcher.InvokeAsync(() => + { + SetCurrentCircuitHost(this); + Log.LocationChange(_logger, CircuitId, uri); + var navigationManager = (RemoteNavigationManager)Services.GetRequiredService(); + navigationManager.NotifyLocationChanged(uri, intercepted); + Log.LocationChangeSucceeded(_logger, CircuitId, uri); + }); + } + catch (Exception ex) + { + // It's up to the NavigationManager implementation to validate the URI. + // + // Note that it's also possible that setting the URI could cause a failure in code that listens + // to NavigationManager.LocationChanged. + // + // In either case, a well-behaved client will not send invalid URIs, and we don't really + // want to continue processing with the circuit if setting the URI failed inside application + // code. The safest thing to do is consider it a critical failure since URI is global state, + // and a failure means that an update to global state was partially applied. + Log.LocationChangeFailed(_logger, CircuitId, uri, ex); UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); } } @@ -328,6 +405,17 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits private static readonly Action _onConnectionUp; private static readonly Action _onConnectionDown; private static readonly Action _onCircuitClosed; + private static readonly Action _beginInvokeDotNetStatic; + private static readonly Action _beginInvokeDotNetInstance; + private static readonly Action _endInvokeDispatchException; + private static readonly Action _endInvokeJSFailed; + private static readonly Action _endInvokeJSSucceeded; + private static readonly Action _dispatchEventFailedToParseEventDescriptor; + private static readonly Action _dispatchEventFailedToDispatchEvent; + private static readonly Action _dispatchEventThroughJSInterop; + private static readonly Action _locationChange; + private static readonly Action _locationChangeSucceeded; + private static readonly Action _locationChangeFailed; private static class EventIds { @@ -337,6 +425,17 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public static readonly EventId OnConnectionUp = new EventId(103, "OnConnectionUp"); public static readonly EventId OnConnectionDown = new EventId(104, "OnConnectionDown"); public static readonly EventId OnCircuitClosed = new EventId(105, "OnCircuitClosed"); + public static readonly EventId InvalidBrowserEventFormat = new EventId(106, "InvalidBrowserEventFormat"); + public static readonly EventId DispatchEventFailedToParseEventDescriptor = new EventId(107, "DispatchEventFailedToParseEventDescriptor"); + public static readonly EventId DispatchEventFailedToDispatchEvent = new EventId(108, "DispatchEventFailedToDispatchEvent"); + public static readonly EventId BeginInvokeDotNet = new EventId(109, "BeginInvokeDotNet"); + public static readonly EventId EndInvokeDispatchException = new EventId(110, "EndInvokeDispatchException"); + public static readonly EventId EndInvokeJSFailed = new EventId(111, "EndInvokeJSFailed"); + public static readonly EventId EndInvokeJSSucceeded = new EventId(112, "EndInvokeJSSucceeded"); + public static readonly EventId DispatchEventThroughJSInterop = new EventId(113, "DispatchEventThroughJSInterop"); + public static readonly EventId LocationChange = new EventId(114, "LocationChange"); + public static readonly EventId LocationChangeSucceded = new EventId(115, "LocationChangeSucceeded"); + public static readonly EventId LocationChangeFailed = new EventId(116, "LocationChangeFailed"); } static Log() @@ -370,6 +469,61 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits LogLevel.Debug, EventIds.OnCircuitClosed, "Closing circuit with id {CircuitId}."); + + _beginInvokeDotNetStatic = LoggerMessage.Define( + LogLevel.Debug, + EventIds.BeginInvokeDotNet, + "Invoking static method with identifier '{MethodIdentifier}' on assembly '{Assembly}' with callback id '{CallId}'"); + + _beginInvokeDotNetInstance = LoggerMessage.Define( + LogLevel.Debug, + EventIds.BeginInvokeDotNet, + "Invoking instance method '{MethodIdentifier}' on instance '{DotNetObjectId}' with callback id '{CallId}'"); + + _endInvokeDispatchException = LoggerMessage.Define( + LogLevel.Debug, + EventIds.EndInvokeDispatchException, + "There was an error invoking 'Microsoft.JSInterop.DotNetDispatcher.EndInvoke'."); + + _endInvokeJSFailed = LoggerMessage.Define( + LogLevel.Debug, + EventIds.EndInvokeJSFailed, + "The JS interop call with callback id '{AsyncCall}' failed with error '{Error}'."); + + _endInvokeJSSucceeded = LoggerMessage.Define( + LogLevel.Debug, + EventIds.EndInvokeJSSucceeded, + "The JS interop call with callback id '{AsyncCall}' succeeded."); + + _dispatchEventFailedToParseEventDescriptor = LoggerMessage.Define( + LogLevel.Debug, + EventIds.DispatchEventFailedToParseEventDescriptor, + "Failed to parse the event descriptor data when trying to dispatch an event."); + + _dispatchEventFailedToDispatchEvent = LoggerMessage.Define( + LogLevel.Debug, + EventIds.DispatchEventFailedToDispatchEvent, + "There was an error dispatching the event '{EventHandlerId}' to the application."); + + _dispatchEventThroughJSInterop = LoggerMessage.Define( + LogLevel.Debug, + EventIds.DispatchEventThroughJSInterop, + "There was an intent to dispatch a browser event through JS interop."); + + _locationChange = LoggerMessage.Define( + LogLevel.Debug, + EventIds.LocationChange, + "Location changing to {URI} in {CircuitId}."); + + _locationChangeSucceeded = LoggerMessage.Define( + LogLevel.Debug, + EventIds.LocationChangeSucceded, + "Location change to {URI} in {CircuitId} succeded."); + + _locationChangeFailed = LoggerMessage.Define( + LogLevel.Debug, + EventIds.LocationChangeFailed, + "Location change to {URI} in {CircuitId} failed."); } public static void UnhandledExceptionInvokingCircuitHandler(ILogger logger, CircuitHandler handler, string handlerMethod, Exception exception) @@ -394,6 +548,36 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public static void CircuitClosed(ILogger logger, string circuitId) => _onCircuitClosed(logger, circuitId, null); + + public static void EndInvokeDispatchException(ILogger logger, Exception ex) => _endInvokeDispatchException(logger, ex); + + public static void EndInvokeJSFailed(ILogger logger, long asyncHandle, string arguments) => _endInvokeJSFailed(logger, asyncHandle, arguments, null); + + public static void EndInvokeJSSucceeded(ILogger logger, long asyncCall) => _endInvokeJSSucceeded(logger, asyncCall, null); + + public static void DispatchEventFailedToParseEventDescriptor(ILogger logger, Exception ex) => _dispatchEventFailedToParseEventDescriptor(logger, ex); + + public static void DispatchEventFailedToDispatchEvent(ILogger logger, string eventHandlerId, Exception ex) => _dispatchEventFailedToDispatchEvent(logger, eventHandlerId ?? "", ex); + + public static void BeginInvokeDotNet(ILogger logger, string callId, string assemblyName, string methodIdentifier, long dotNetObjectId) + { + if (assemblyName != null) + { + _beginInvokeDotNetStatic(logger, methodIdentifier, assemblyName, callId, null); + } + else + { + _beginInvokeDotNetInstance(logger, methodIdentifier, dotNetObjectId, callId, null); + } + } + + public static void DispatchEventTroughJSInterop(ILogger logger) => _dispatchEventThroughJSInterop(logger, null); + + public static void LocationChange(ILogger logger, string circuitId, string uri) => _locationChange(logger, circuitId, uri, null); + + public static void LocationChangeSucceeded(ILogger logger, string circuitId, string uri) => _locationChangeSucceeded(logger, circuitId, uri, null); + + public static void LocationChangeFailed(ILogger logger, string circuitId, string uri, Exception exception) => _locationChangeFailed(logger, circuitId, uri, exception); } } } diff --git a/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs b/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs index 3f619698f1..ac7be32523 100644 --- a/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs +++ b/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Server public void Configure(CircuitOptions options) { - options.JSInteropDetailedErrors = Configuration.GetValue(WebHostDefaults.DetailedErrorsKey); + options.DetailedErrors = Configuration.GetValue(WebHostDefaults.DetailedErrorsKey); } } } diff --git a/src/Components/Server/src/Circuits/CircuitPrerenderer.cs b/src/Components/Server/src/Circuits/CircuitPrerenderer.cs deleted file mode 100644 index 4ac595656c..0000000000 --- a/src/Components/Server/src/Circuits/CircuitPrerenderer.cs +++ /dev/null @@ -1,206 +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.Runtime.ExceptionServices; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; - -namespace Microsoft.AspNetCore.Components.Server.Circuits -{ - internal class CircuitPrerenderer : IComponentPrerenderer - { - private static object CircuitHostKey = new object(); - private static object CancellationStatusKey = new object(); - private static readonly JsonSerializerOptions _jsonSerializationOptions = - new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly CircuitFactory _circuitFactory; - private readonly CircuitRegistry _registry; - - public CircuitPrerenderer( - CircuitFactory circuitFactory, - CircuitRegistry registry) - { - _circuitFactory = circuitFactory; - _registry = registry; - } - - public async Task PrerenderComponentAsync(ComponentPrerenderingContext prerenderingContext) - { - var context = prerenderingContext.Context; - var cancellationStatus = GetOrCreateCancellationStatus(context); - if (cancellationStatus.Canceled) - { - // Avoid creating a circuit host if other component earlier in the pipeline already triggered - // cancellation (e.g., by navigating or throwing). Instead render nothing. - return new ComponentPrerenderResult(Array.Empty()); - } - var circuitHost = GetOrCreateCircuitHost(context, cancellationStatus); - ComponentRenderedText renderResult; - try - { - renderResult = await circuitHost.PrerenderComponentAsync( - prerenderingContext.ComponentType, - prerenderingContext.Parameters); - } - catch (NavigationException navigationException) - { - // Cleanup the state as we won't need it any longer. - // Signal callbacks that we don't have to register the circuit. - await CleanupCircuitState(context, cancellationStatus, circuitHost); - - // Navigation was attempted during prerendering. - if (prerenderingContext.Context.Response.HasStarted) - { - // We can't perform a redirect as the server already started sending the response. - // This is considered an application error as the developer should buffer the response until - // all components have rendered. - throw new InvalidOperationException("A navigation command was attempted during prerendering after the server already started sending the response. " + - "Navigation commands can not be issued during server-side prerendering after the response from the server has started. Applications must buffer the" + - "reponse and avoid using features like FlushAsync() before all components on the page have been rendered to prevent failed navigation commands.", navigationException); - } - - context.Response.Redirect(navigationException.Location); - return new ComponentPrerenderResult(Array.Empty()); - } - catch - { - // If prerendering any component fails, cancel prerendering entirely and dispose the DI scope - await CleanupCircuitState(context, cancellationStatus, circuitHost); - throw; - } - - circuitHost.Descriptors.Add(new ComponentDescriptor - { - ComponentType = prerenderingContext.ComponentType, - Prerendered = true - }); - - var record = JsonSerializer.Serialize(new PrerenderedComponentRecord( - // We need to do this due to the fact that -- is not allowed within HTML comments and HTML doesn't encode '-'. - // We will never have '..' sequences because we Base64UrlEncode the circuit id - circuitHost.CircuitId.Replace("--", ".."), - circuitHost.Renderer.Id, - renderResult.ComponentId), - _jsonSerializationOptions); - - var result = (new[] { - $"", - }).Concat(renderResult.Tokens).Concat( - new[] { - $"" - }); - - return new ComponentPrerenderResult(result); - } - - private PrerenderingCancellationStatus GetOrCreateCancellationStatus(HttpContext context) - { - if (context.Items.TryGetValue(CancellationStatusKey, out var existingValue)) - { - return (PrerenderingCancellationStatus)existingValue; - } - else - { - var cancellationStatus = new PrerenderingCancellationStatus(); - context.Items[CancellationStatusKey] = cancellationStatus; - return cancellationStatus; - } - } - - private static async Task CleanupCircuitState(HttpContext context, PrerenderingCancellationStatus cancellationStatus, CircuitHost circuitHost) - { - cancellationStatus.Canceled = true; - context.Items.Remove(CircuitHostKey); - await circuitHost.DisposeAsync(); - } - - private CircuitHost GetOrCreateCircuitHost(HttpContext context, PrerenderingCancellationStatus cancellationStatus) - { - if (context.Items.TryGetValue(CircuitHostKey, out var existingHost)) - { - return (CircuitHost)existingHost; - } - else - { - var result = _circuitFactory.CreateCircuitHost( - context, - client: new CircuitClientProxy(), // This creates an "offline" client. - GetFullUri(context.Request), - GetFullBaseUri(context.Request)); - - result.UnhandledException += CircuitHost_UnhandledException; - context.Response.OnCompleted(() => - { - result.UnhandledException -= CircuitHost_UnhandledException; - if (!cancellationStatus.Canceled) - { - _registry.RegisterDisconnectedCircuit(result); - } - - return Task.CompletedTask; - }); - context.Items.Add(CircuitHostKey, result); - - return result; - } - } - - private void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - // Throw all exceptions encountered during pre-rendering so the default developer - // error page can respond. - ExceptionDispatchInfo.Capture((Exception)e.ExceptionObject).Throw(); - } - - private string GetFullUri(HttpRequest request) - { - return UriHelper.BuildAbsolute( - request.Scheme, - request.Host, - request.PathBase, - request.Path, - request.QueryString); - } - - private string GetFullBaseUri(HttpRequest request) - { - var result = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase); - - // PathBase may be "/" or "/some/thing", but to be a well-formed base URI - // it has to end with a trailing slash - if (!result.EndsWith('/')) - { - result += '/'; - } - - return result; - } - - private readonly struct PrerenderedComponentRecord - { - public PrerenderedComponentRecord(string circuitId, int rendererId, int componentId) - { - CircuitId = circuitId; - RendererId = rendererId; - ComponentId = componentId; - } - - public string CircuitId { get; } - - public int RendererId { get; } - - public int ComponentId { get; } - } - - private class PrerenderingCancellationStatus - { - public bool Canceled { get; set; } - } - } -} diff --git a/src/Components/Server/src/Circuits/CircuitRegistry.cs b/src/Components/Server/src/Circuits/CircuitRegistry.cs index 2c57ce63f5..9fe25c5b68 100644 --- a/src/Components/Server/src/Circuits/CircuitRegistry.cs +++ b/src/Components/Server/src/Circuits/CircuitRegistry.cs @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits DisconnectedCircuits = new MemoryCache(new MemoryCacheOptions { - SizeLimit = _options.MaxRetainedDisconnectedCircuits, + SizeLimit = _options.DisconnectedCircuitMaxRetained, }); _postEvictionCallback = new PostEvictionCallbackRegistration @@ -81,6 +81,15 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits } } + public void PermanentDisconnect(CircuitHost circuitHost) + { + if (ConnectedCircuits.TryRemove(circuitHost.CircuitId, out _)) + { + Log.CircuitDisconnectedPermanently(_logger, circuitHost.CircuitId); + circuitHost.Client.SetDisconnected(); + } + } + public virtual Task DisconnectAsync(CircuitHost circuitHost, string connectionId) { Log.CircuitDisconnectStarted(_logger, circuitHost.CircuitId, connectionId); @@ -314,6 +323,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits private static readonly Action _circuitNotActive; private static readonly Action _circuitConnectedToDifferentConnection; private static readonly Action _circuitMarkedDisconnected; + private static readonly Action _circuitDisconnectedPermanently; private static readonly Action _circuitEvicted; private static class EventIds @@ -330,6 +340,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public static readonly EventId CircuitConnectedToDifferentConnection = new EventId(109, "CircuitConnectedToDifferentConnection"); public static readonly EventId CircuitMarkedDisconnected = new EventId(110, "CircuitMarkedDisconnected"); public static readonly EventId CircuitEvicted = new EventId(111, "CircuitEvicted"); + public static readonly EventId CircuitDisconnectedPermanently = new EventId(112, "CircuitDisconnectedPermanently"); } static Log() @@ -394,6 +405,11 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits EventIds.CircuitMarkedDisconnected, "Circuit with id {CircuitId} is disconnected."); + _circuitDisconnectedPermanently = LoggerMessage.Define( + LogLevel.Debug, + EventIds.CircuitDisconnectedPermanently, + "Circuit with id {CircuitId} has been removed from the registry for permanent disconnection."); + _circuitEvicted = LoggerMessage.Define( LogLevel.Debug, EventIds.CircuitEvicted, @@ -436,6 +452,9 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public static void CircuitMarkedDisconnected(ILogger logger, string circuitId) => _circuitMarkedDisconnected(logger, circuitId, null); + public static void CircuitDisconnectedPermanently(ILogger logger, string circuitId) => + _circuitDisconnectedPermanently(logger, circuitId, null); + public static void CircuitEvicted(ILogger logger, string circuitId, EvictionReason evictionReason) => _circuitEvicted(logger, circuitId, evictionReason, null); } diff --git a/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs b/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs index c08db124bc..d353d5dc2c 100644 --- a/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs +++ b/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs @@ -4,16 +4,17 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web.Rendering; -using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Routing; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.JSInterop; +using System.Threading.Tasks; namespace Microsoft.AspNetCore.Components.Server.Circuits { @@ -38,9 +39,12 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public override CircuitHost CreateCircuitHost( HttpContext httpContext, CircuitClientProxy client, - string uriAbsolute, - string baseUriAbsolute) + string baseUri, + string uri, + ClaimsPrincipal user) { + // We do as much intialization as possible eagerly in this method, which makes the error handling + // story much simpler. If we throw from here, it's handled inside the initial hub method. var components = ResolveComponentMetadata(httpContext, client); var scope = _scopeFactory.CreateScope(); @@ -50,24 +54,25 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits jsRuntime.Initialize(client); componentContext.Initialize(client); - // You can replace the AuthenticationStateProvider with a custom one, but in that case initialization is up to you - var authenticationStateProvider = scope.ServiceProvider.GetService(); - (authenticationStateProvider as FixedAuthenticationStateProvider)?.Initialize(httpContext.User); + var authenticationStateProvider = scope.ServiceProvider.GetService() as IHostEnvironmentAuthenticationStateProvider; + if (authenticationStateProvider != null) + { + var authenticationState = new AuthenticationState(httpContext.User); // TODO: Get this from the hub connection context instead + authenticationStateProvider.SetAuthenticationState(Task.FromResult(authenticationState)); + } - var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService(); + var navigationManager = (RemoteNavigationManager)scope.ServiceProvider.GetRequiredService(); var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService(); if (client.Connected) { - uriHelper.AttachJsRuntime(jsRuntime); - uriHelper.InitializeState( - uriAbsolute, - baseUriAbsolute); + navigationManager.AttachJsRuntime(jsRuntime); + navigationManager.Initialize(baseUri, uri); navigationInterception.AttachJSRuntime(jsRuntime); } else { - uriHelper.InitializeState(uriAbsolute, baseUriAbsolute); + navigationManager.Initialize(baseUri, uri); } var rendererRegistry = new RendererRegistry(); @@ -98,11 +103,12 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits // Initialize per - circuit data that services need (circuitHost.Services.GetRequiredService() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; + circuitHost.SetCircuitUser(user); return circuitHost; } - internal static IList ResolveComponentMetadata(HttpContext httpContext, CircuitClientProxy client) + internal static List ResolveComponentMetadata(HttpContext httpContext, CircuitClientProxy client) { if (!client.Connected) { diff --git a/src/Components/Server/src/Circuits/FixedAuthenticationStateProvider.cs b/src/Components/Server/src/Circuits/FixedAuthenticationStateProvider.cs deleted file mode 100644 index 41c0942cd8..0000000000 --- a/src/Components/Server/src/Circuits/FixedAuthenticationStateProvider.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; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.AspNetCore.Components.Server.Circuits -{ - /// - /// An intended for use in server-side - /// Blazor. The circuit factory will supply a from - /// the current , which will stay fixed for the - /// lifetime of the circuit since cannot change. - /// - /// This can therefore only be used with redirect-style authentication flows, - /// since it requires a new HTTP request in order to become a different user. - /// - internal class FixedAuthenticationStateProvider : AuthenticationStateProvider - { - private Task _authenticationStateTask; - - public void Initialize(ClaimsPrincipal user) - { - _authenticationStateTask = Task.FromResult(new AuthenticationState(user)); - } - - public override Task GetAuthenticationStateAsync() - => _authenticationStateTask - ?? throw new InvalidOperationException($"{nameof(GetAuthenticationStateAsync)} was called before {nameof(Initialize)}."); - } -} diff --git a/src/Components/Server/src/Circuits/RemoteJSRuntime.cs b/src/Components/Server/src/Circuits/RemoteJSRuntime.cs index 34649ddb9b..442775d451 100644 --- a/src/Components/Server/src/Circuits/RemoteJSRuntime.cs +++ b/src/Components/Server/src/Circuits/RemoteJSRuntime.cs @@ -2,7 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Runtime.ExceptionServices; +using System.Text.Json; using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.JSInterop; @@ -11,11 +14,13 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits internal class RemoteJSRuntime : JSRuntimeBase { private readonly CircuitOptions _options; + private readonly ILogger _logger; private CircuitClientProxy _clientProxy; - public RemoteJSRuntime(IOptions options) + public RemoteJSRuntime(IOptions options, ILogger logger) { _options = options.Value; + _logger = logger; DefaultAsyncTimeout = _options.JSInteropDefaultCallTimeout; } @@ -24,17 +29,36 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits _clientProxy = clientProxy ?? throw new ArgumentNullException(nameof(clientProxy)); } - protected override object OnDotNetInvocationException(Exception exception, string assemblyName, string methodIdentifier) + protected override void EndInvokeDotNet(string callId, bool success, object resultOrError, string assemblyName, string methodIdentifier, long dotNetObjectId) { - if (_options.JSInteropDetailedErrors) + if (!success) { - return base.OnDotNetInvocationException(exception, assemblyName, methodIdentifier); + var actualException = resultOrError is Exception ex ? ex : resultOrError is ExceptionDispatchInfo edi ? edi.SourceException : resultOrError; + Log.InvokeDotNetMethodException(_logger, callId, assemblyName, methodIdentifier, dotNetObjectId, actualException as Exception); + if (_options.DetailedErrors) + { + EndInvokeDotNetCore(callId, success, actualException.ToString()); + } + else + { + var message = $"There was an exception invoking '{methodIdentifier}' on assembly '{assemblyName}'. For more details turn on " + + $"detailed exceptions in '{typeof(CircuitOptions).Name}.{nameof(CircuitOptions.DetailedErrors)}'"; + + EndInvokeDotNetCore(callId, success, message); + } } + else + { + Log.InvokeDotNetMethodSuccess(_logger, callId, assemblyName, methodIdentifier, dotNetObjectId); + EndInvokeDotNetCore(callId, success, resultOrError); + } + } - var message = $"There was an exception invoking '{methodIdentifier}' on assembly '{assemblyName}'. For more details turn on " + - $"detailed exceptions in '{typeof(CircuitOptions).Name}.{nameof(CircuitOptions.JSInteropDetailedErrors)}'"; - - return message; + private void EndInvokeDotNetCore(string callId, bool success, object resultOrError) + { + _clientProxy.SendAsync( + "JS.EndInvokeDotNet", + JsonSerializer.Serialize(new[] { callId, success, resultOrError }, JsonSerializerOptionsProvider.Options)); } protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson) @@ -47,7 +71,71 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits "attempted during prerendering or while the client is disconnected."); } + Log.BeginInvokeJS(_logger, asyncHandle, identifier); + _clientProxy.SendAsync("JS.BeginInvokeJS", asyncHandle, identifier, argsJson); } + + public static class Log + { + private static readonly Action _beginInvokeJS = + LoggerMessage.Define( + LogLevel.Debug, + new EventId(1, "BeginInvokeJS"), + "Begin invoke JS interop '{AsyncHandle}': '{FunctionIdentifier}'"); + + private static readonly Action _invokeStaticDotNetMethodException = + LoggerMessage.Define( + LogLevel.Debug, + new EventId(2, "InvokeDotNetMethodException"), + "There was an error invoking the static method '[{AssemblyName}]::{MethodIdentifier}' with callback id '{CallbackId}'."); + + private static readonly Action _invokeInstanceDotNetMethodException = + LoggerMessage.Define( + LogLevel.Debug, + new EventId(2, "InvokeDotNetMethodException"), + "There was an error invoking the instance method '{MethodIdentifier}' on reference '{DotNetObjectReference}' with callback id '{CallbackId}'."); + + private static readonly Action _invokeStaticDotNetMethodSuccess = + LoggerMessage.Define( + LogLevel.Debug, + new EventId(3, "InvokeDotNetMethodSuccess"), + "Invocation of '[{AssemblyName}]::{MethodIdentifier}' with callback id '{CallbackId}' completed successfully."); + + private static readonly Action _invokeInstanceDotNetMethodSuccess = + LoggerMessage.Define( + LogLevel.Debug, + new EventId(3, "InvokeDotNetMethodSuccess"), + "Invocation of '{MethodIdentifier}' on reference '{DotNetObjectReference}' with callback id '{CallbackId}' completed successfully."); + + + internal static void BeginInvokeJS(ILogger logger, long asyncHandle, string identifier) => + _beginInvokeJS(logger, asyncHandle, identifier, null); + + internal static void InvokeDotNetMethodException(ILogger logger, string callId, string assemblyName, string methodIdentifier, long dotNetObjectReference, Exception exception) + { + if (assemblyName != null) + { + _invokeStaticDotNetMethodException(logger, assemblyName, methodIdentifier, callId, exception); + } + else + { + _invokeInstanceDotNetMethodException(logger, methodIdentifier, dotNetObjectReference, callId, exception); + } + } + + internal static void InvokeDotNetMethodSuccess(ILogger logger, string callId, string assemblyName, string methodIdentifier, long dotNetObjectId) + { + if (assemblyName != null) + { + _invokeStaticDotNetMethodSuccess(logger, assemblyName, methodIdentifier, callId, null); + } + else + { + _invokeInstanceDotNetMethodSuccess(logger, methodIdentifier, dotNetObjectId, callId, null); + } + + } + } } } diff --git a/src/Components/Server/src/Circuits/RemoteNavigationInterception.cs b/src/Components/Server/src/Circuits/RemoteNavigationInterception.cs index 3609adf95d..1a689621e5 100644 --- a/src/Components/Server/src/Circuits/RemoteNavigationInterception.cs +++ b/src/Components/Server/src/Circuits/RemoteNavigationInterception.cs @@ -5,7 +5,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Routing; using Microsoft.JSInterop; -using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop; +using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop; namespace Microsoft.AspNetCore.Components.Server.Circuits { diff --git a/src/Components/Server/src/Circuits/RemoteUriHelper.cs b/src/Components/Server/src/Circuits/RemoteNavigationManager.cs similarity index 55% rename from src/Components/Server/src/Circuits/RemoteUriHelper.cs rename to src/Components/Server/src/Circuits/RemoteNavigationManager.cs index e9a1b28494..b57130c29a 100644 --- a/src/Components/Server/src/Circuits/RemoteUriHelper.cs +++ b/src/Components/Server/src/Circuits/RemoteNavigationManager.cs @@ -2,26 +2,26 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Components.Routing; using Microsoft.Extensions.Logging; using Microsoft.JSInterop; -using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop; +using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop; namespace Microsoft.AspNetCore.Components.Server.Circuits { /// - /// A Server-Side Components implementation of . + /// A Server-Side Blazor implementation of . /// - internal class RemoteUriHelper : UriHelperBase + internal class RemoteNavigationManager : NavigationManager, IHostEnvironmentNavigationManager { - private readonly ILogger _logger; + private readonly ILogger _logger; private IJSRuntime _jsRuntime; /// - /// Creates a new instance. + /// Creates a new instance. /// /// The . - public RemoteUriHelper(ILogger logger) + public RemoteNavigationManager(ILogger logger) { _logger = logger; } @@ -32,21 +32,21 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public bool HasAttachedJSRuntime => _jsRuntime != null; /// - /// Initializes the . + /// Initializes the . /// - /// The absolute URI of the current page. - /// The absolute base URI of the current page. - public override void InitializeState(string uriAbsolute, string baseUriAbsolute) + /// The base URI. + /// The absolute URI. + public new void Initialize(string baseUri, string uri) { - base.InitializeState(uriAbsolute, baseUriAbsolute); - TriggerOnLocationChanged(isinterceptedLink: false); + base.Initialize(baseUri, uri); + NotifyLocationChanged(isInterceptedLink: false); } /// - /// Initializes the . + /// Initializes the . /// /// The to use for interoperability. - internal void AttachJsRuntime(IJSRuntime jsRuntime) + public void AttachJsRuntime(IJSRuntime jsRuntime) { if (_jsRuntime != null) { @@ -54,31 +54,14 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits } _jsRuntime = jsRuntime; - - _jsRuntime.InvokeAsync( - Interop.ListenForNavigationEvents, - typeof(RemoteUriHelper).Assembly.GetName().Name, - nameof(NotifyLocationChanged)); } - /// - /// For framework use only. - /// - [JSInvokable(nameof(NotifyLocationChanged))] - public static void NotifyLocationChanged(string uriAbsolute, bool isInterceptedLink) + public void NotifyLocationChanged(string uri, bool intercepted) { - var circuit = CircuitHost.Current; - if (circuit == null) - { - var message = $"{nameof(NotifyLocationChanged)} called without a circuit."; - throw new InvalidOperationException(message); - } + Log.ReceivedLocationChangedNotification(_logger, uri, intercepted); - var uriHelper = (RemoteUriHelper)circuit.Services.GetRequiredService(); - Log.ReceivedLocationChangedNotification(uriHelper._logger, uriAbsolute, isInterceptedLink); - - uriHelper.SetAbsoluteUri(uriAbsolute); - uriHelper.TriggerOnLocationChanged(isInterceptedLink); + Uri = uri; + NotifyLocationChanged(intercepted); } /// @@ -88,8 +71,10 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits if (_jsRuntime == null) { - throw new NavigationException(uri); + var absoluteUriString = ToAbsoluteUri(uri).ToString(); + throw new NavigationException(absoluteUriString); } + _jsRuntime.InvokeAsync(Interop.NavigateTo, uri, forceLoad); } diff --git a/src/Components/Server/src/Circuits/RemoteRenderer.cs b/src/Components/Server/src/Circuits/RemoteRenderer.cs index 8065ca4afd..8b9ebb341a 100644 --- a/src/Components/Server/src/Circuits/RemoteRenderer.cs +++ b/src/Components/Server/src/Circuits/RemoteRenderer.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Concurrent; -using System.IO; +using System.Diagnostics; using System.Linq; using System.Text.Encodings.Web; using System.Threading; @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging; using Microsoft.JSInterop; @@ -53,7 +54,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering _logger = logger; } - internal ConcurrentQueue PendingRenderBatches = new ConcurrentQueue(); + internal ConcurrentQueue UnacknowledgedRenderBatches = new ConcurrentQueue(); public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); @@ -102,12 +103,13 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering protected override void Dispose(bool disposing) { _disposing = true; - base.Dispose(true); - while (PendingRenderBatches.TryDequeue(out var entry)) + _rendererRegistry.TryRemove(Id); + while (UnacknowledgedRenderBatches.TryDequeue(out var entry)) { entry.CompletionSource.TrySetCanceled(); + entry.Data.Dispose(); } - _rendererRegistry.TryRemove(Id); + base.Dispose(true); } /// @@ -123,30 +125,35 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering // SignalR's SendAsync can wait an arbitrary duration before serializing the params. // The RenderBatch buffer will get reused by subsequent renders, so we need to // snapshot its contents now. - // TODO: Consider using some kind of array pool instead of allocating a new - // buffer on every render. - byte[] batchBytes; - using (var memoryStream = new MemoryStream()) + var arrayBuilder = new ArrayBuilder(2048); + using var memoryStream = new ArrayBuilderMemoryStream(arrayBuilder); + UnacknowledgedRenderBatch pendingRender; + try { using (var renderBatchWriter = new RenderBatchWriter(memoryStream, false)) { renderBatchWriter.Write(in batch); } - batchBytes = memoryStream.ToArray(); + var renderId = Interlocked.Increment(ref _nextRenderId); + + pendingRender = new UnacknowledgedRenderBatch( + renderId, + arrayBuilder, + new TaskCompletionSource(), + ValueStopwatch.StartNew()); + + // Buffer the rendered batches no matter what. We'll send it down immediately when the client + // is connected or right after the client reconnects. + + UnacknowledgedRenderBatches.Enqueue(pendingRender); + } + catch + { + // if we throw prior to queueing the write, dispose the builder. + arrayBuilder.Dispose(); + throw; } - - var renderId = Interlocked.Increment(ref _nextRenderId); - - var pendingRender = new PendingRender( - renderId, - batchBytes, - new TaskCompletionSource()); - - // Buffer the rendered batches no matter what. We'll send it down immediately when the client - // is connected or right after the client reconnects. - - PendingRenderBatches.Enqueue(pendingRender); // Fire and forget the initial send for this batch (if connected). Otherwise it will be sent // as soon as the client reconnects. @@ -160,10 +167,10 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering // All the batches are sent in order based on the fact that SignalR // provides ordering for the underlying messages and that the batches // are always in order. - return Task.WhenAll(PendingRenderBatches.Select(b => WriteBatchBytesAsync(b))); + return Task.WhenAll(UnacknowledgedRenderBatches.Select(b => WriteBatchBytesAsync(b))); } - private async Task WriteBatchBytesAsync(PendingRender pending) + private async Task WriteBatchBytesAsync(UnacknowledgedRenderBatch pending) { // Send the render batch to the client // If the "send" operation fails (synchronously or asynchronously) or the client @@ -181,8 +188,9 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering return; } - Log.BeginUpdateDisplayAsync(_logger, _client.ConnectionId, pending.BatchId, pending.Data.Length); - await _client.SendAsync("JS.RenderBatch", Id, pending.BatchId, pending.Data); + Log.BeginUpdateDisplayAsync(_logger, _client.ConnectionId, pending.BatchId, pending.Data.Count); + var segment = new ArraySegment(pending.Data.Buffer, 0, pending.Data.Count); + await _client.SendAsync("JS.RenderBatch", Id, pending.BatchId, segment); } catch (Exception e) { @@ -203,30 +211,68 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering return; } + // When clients send acks we know for sure they received and applied the batch. + // We send batches right away, and hold them in memory until we receive an ACK. + // If one or more client ACKs get lost (e.g., with long polling, client->server delivery is not guaranteed) + // we might receive an ack for a higher batch. + // We confirm all previous batches at that point (because receiving an ack is guarantee + // from the client that it has received and successfully applied all batches up to that point). + + // If receive an ack for a previously acknowledged batch, its an error, as the messages are + // guranteed to be delivered in order, so a message for a render batch of 2 will never arrive + // after a message for a render batch for 3. + // If that were to be the case, it would just be enough to relax the checks here and simply skip + // the message. + + // A batch might get lost when we send it to the client, because the client might disconnect before receiving and processing it. + // In this case, once it reconnects the server will re-send any unacknowledged batches, some of which the + // client might have received and even believe it did send back an acknowledgement for. The client handles + // those by re-acknowledging. + // Even though we're not on the renderer sync context here, it's safe to assume ordered execution of the following // line (i.e., matching the order in which we received batch completion messages) based on the fact that SignalR // synchronizes calls to hub methods. That is, it won't issue more than one call to this method from the same hub // at the same time on different threads. - if (!PendingRenderBatches.TryDequeue(out var entry) || entry.BatchId != incomingBatchId) + + if (!UnacknowledgedRenderBatches.TryPeek(out var nextUnacknowledgedBatch) || incomingBatchId < nextUnacknowledgedBatch.BatchId) { - HandleException( - new InvalidOperationException($"Received a notification for a rendered batch when not expecting it. Batch id '{incomingBatchId}'.")); + Log.ReceivedDuplicateBatchAck(_logger, incomingBatchId); } else { - if (errorMessageOrNull == null) + var lastBatchId = nextUnacknowledgedBatch.BatchId; + // Order is important here so that we don't prematurely dequeue the last nextUnacknowledgedBatch + while (UnacknowledgedRenderBatches.TryPeek(out nextUnacknowledgedBatch) && nextUnacknowledgedBatch.BatchId <= incomingBatchId) { - Log.CompletingBatchWithoutError(_logger, entry.BatchId); - } - else - { - Log.CompletingBatchWithError(_logger, entry.BatchId, errorMessageOrNull); + lastBatchId = nextUnacknowledgedBatch.BatchId; + UnacknowledgedRenderBatches.TryDequeue(out _); + ProcessPendingBatch(errorMessageOrNull, nextUnacknowledgedBatch); } - CompleteRender(entry.CompletionSource, errorMessageOrNull); + if (lastBatchId < incomingBatchId) + { + HandleException( + new InvalidOperationException($"Received an acknowledgement for batch with id '{incomingBatchId}' when the last batch produced was '{lastBatchId}'.")); + } } } + private void ProcessPendingBatch(string errorMessageOrNull, UnacknowledgedRenderBatch entry) + { + var elapsedTime = entry.ValueStopwatch.GetElapsedTime(); + if (errorMessageOrNull == null) + { + Log.CompletingBatchWithoutError(_logger, entry.BatchId, elapsedTime); + } + else + { + Log.CompletingBatchWithError(_logger, entry.BatchId, errorMessageOrNull, elapsedTime); + } + + entry.Data.Dispose(); + CompleteRender(entry.CompletionSource, errorMessageOrNull); + } + private void CompleteRender(TaskCompletionSource pendingRenderInfo, string errorMessageOrNull) { if (errorMessageOrNull == null) @@ -239,18 +285,20 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering } } - internal readonly struct PendingRender + internal readonly struct UnacknowledgedRenderBatch { - public PendingRender(long batchId, byte[] data, TaskCompletionSource completionSource) + public UnacknowledgedRenderBatch(long batchId, ArrayBuilder data, TaskCompletionSource completionSource, ValueStopwatch valueStopwatch) { BatchId = batchId; Data = data; CompletionSource = completionSource; + ValueStopwatch = valueStopwatch; } public long BatchId { get; } - public byte[] Data { get; } + public ArrayBuilder Data { get; } public TaskCompletionSource CompletionSource { get; } + public ValueStopwatch ValueStopwatch { get; } } private void CaptureAsyncExceptions(Task task) @@ -270,8 +318,9 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering private static readonly Action _beginUpdateDisplayAsync; private static readonly Action _bufferingRenderDisconnectedClient; private static readonly Action _sendBatchDataFailed; - private static readonly Action _completingBatchWithError; - private static readonly Action _completingBatchWithoutError; + private static readonly Action _completingBatchWithError; + private static readonly Action _completingBatchWithoutError; + private static readonly Action _receivedDuplicateBatchAcknowledgement; private static class EventIds { @@ -281,6 +330,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering public static readonly EventId SendBatchDataFailed = new EventId(103, "SendBatchDataFailed"); public static readonly EventId CompletingBatchWithError = new EventId(104, "CompletingBatchWithError"); public static readonly EventId CompletingBatchWithoutError = new EventId(105, "CompletingBatchWithoutError"); + public static readonly EventId ReceivedDuplicateBatchAcknowledgement = new EventId(106, "ReceivedDuplicateBatchAcknowledgement"); } static Log() @@ -305,15 +355,20 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering EventIds.SendBatchDataFailed, "Sending data for batch failed: {Message}"); - _completingBatchWithError = LoggerMessage.Define( + _completingBatchWithError = LoggerMessage.Define( LogLevel.Debug, EventIds.CompletingBatchWithError, - "Completing batch {BatchId} with error: {ErrorMessage}"); + "Completing batch {BatchId} with error: {ErrorMessage} in {ElapsedMilliseconds}ms."); - _completingBatchWithoutError = LoggerMessage.Define( + _completingBatchWithoutError = LoggerMessage.Define( LogLevel.Debug, EventIds.CompletingBatchWithoutError, - "Completing batch {BatchId} without error"); + "Completing batch {BatchId} without error in {ElapsedMilliseconds}ms."); + + _receivedDuplicateBatchAcknowledgement = LoggerMessage.Define( + LogLevel.Debug, + EventIds.ReceivedDuplicateBatchAcknowledgement, + "Received a duplicate ACK for batch id '{IncomingBatchId}'."); } public static void SendBatchDataFailed(ILogger logger, Exception exception) @@ -347,22 +402,29 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering null); } - public static void CompletingBatchWithError(ILogger logger, long batchId, string errorMessage) + public static void CompletingBatchWithError(ILogger logger, long batchId, string errorMessage, TimeSpan elapsedTime) { _completingBatchWithError( logger, batchId, errorMessage, + elapsedTime.TotalMilliseconds, null); } - public static void CompletingBatchWithoutError(ILogger logger, long batchId) + public static void CompletingBatchWithoutError(ILogger logger, long batchId, TimeSpan elapsedTime) { _completingBatchWithoutError( logger, batchId, + elapsedTime.TotalMilliseconds, null); } + + internal static void ReceivedDuplicateBatchAck(ILogger logger, long incomingBatchId) + { + _receivedDuplicateBatchAcknowledgement(logger, incomingBatchId, null); + } } } } diff --git a/src/Components/Server/src/Circuits/RemoteRendererException.cs b/src/Components/Server/src/Circuits/RemoteRendererException.cs index 462c446751..75edc46ad7 100644 --- a/src/Components/Server/src/Circuits/RemoteRendererException.cs +++ b/src/Components/Server/src/Circuits/RemoteRendererException.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering /// /// Represents an exception related to remote rendering. /// - public class RemoteRendererException : Exception + internal class RemoteRendererException : Exception { /// /// Constructs an instance of . diff --git a/src/Components/Server/src/Circuits/RenderBatchWriter.cs b/src/Components/Server/src/Circuits/RenderBatchWriter.cs index ef035de4ba..f71da86e59 100644 --- a/src/Components/Server/src/Circuits/RenderBatchWriter.cs +++ b/src/Components/Server/src/Circuits/RenderBatchWriter.cs @@ -1,14 +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 Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; using System; using System.Collections.Generic; using System.IO; using System.Text; +using Microsoft.AspNetCore.Components.Rendering; +using Microsoft.AspNetCore.Components.RenderTree; -namespace Microsoft.AspNetCore.Components.Server.Circuits +namespace Microsoft.AspNetCore.Components.Web.Rendering { // TODO: We should consider *not* having this type of infrastructure in the .Server // project, but instead in some new project called .Remote or similar, since it @@ -33,13 +33,13 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits /// internal class RenderBatchWriter : IDisposable { - private readonly List _strings; + private readonly ArrayBuilder _strings; private readonly Dictionary _deduplicatedStringIndices; private readonly BinaryWriter _binaryWriter; public RenderBatchWriter(Stream output, bool leaveOpen) { - _strings = new List(); + _strings = new ArrayBuilder(); _deduplicatedStringIndices = new Dictionary(); _binaryWriter = new BinaryWriter(output, Encoding.UTF8, leaveOpen); } @@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits if (!allowDeduplication || !_deduplicatedStringIndices.TryGetValue(value, out stringIndex)) { stringIndex = _strings.Count; - _strings.Add(value); + _strings.Append(value); if (allowDeduplication) { @@ -263,7 +263,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits for (var i = 0; i < stringsCount; i++) { - var stringValue = _strings[i]; + var stringValue = _strings.Buffer[i]; locations[i] = (int)_binaryWriter.BaseStream.Position; _binaryWriter.Write(stringValue); } @@ -295,6 +295,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public void Dispose() { + _strings.Dispose(); _binaryWriter.Dispose(); } } diff --git a/src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs b/src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs new file mode 100644 index 0000000000..bd1fecfa68 --- /dev/null +++ b/src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs @@ -0,0 +1,26 @@ +// Copyright (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.Server.Circuits +{ + /// + /// An intended for use in server-side Blazor. + /// + internal class ServerAuthenticationStateProvider : AuthenticationStateProvider, IHostEnvironmentAuthenticationStateProvider + { + private Task _authenticationStateTask; + + public override Task GetAuthenticationStateAsync() + => _authenticationStateTask + ?? throw new InvalidOperationException($"{nameof(GetAuthenticationStateAsync)} was called before {nameof(SetAuthenticationState)}."); + + public void SetAuthenticationState(Task authenticationStateTask) + { + _authenticationStateTask = authenticationStateTask ?? throw new ArgumentNullException(nameof(authenticationStateTask)); + NotifyAuthenticationStateChanged(_authenticationStateTask); + } + } +} diff --git a/src/Components/Server/src/DependencyInjection/ComponentDescriptor.cs b/src/Components/Server/src/ComponentDescriptor.cs similarity index 81% rename from src/Components/Server/src/DependencyInjection/ComponentDescriptor.cs rename to src/Components/Server/src/ComponentDescriptor.cs index c97debe7db..30c6319974 100644 --- a/src/Components/Server/src/DependencyInjection/ComponentDescriptor.cs +++ b/src/Components/Server/src/ComponentDescriptor.cs @@ -11,13 +11,10 @@ namespace Microsoft.AspNetCore.Components.Server public string Selector { get; set; } - public bool Prerendered { get; set; } - - public void Deconstruct(out Type componentType, out string selector, out bool prerendered) + public void Deconstruct(out Type componentType, out string selector) { componentType = ComponentType; selector = Selector; - prerendered = Prerendered; } } } diff --git a/src/Components/Server/src/ComponentHub.cs b/src/Components/Server/src/ComponentHub.cs index 4357527b5f..4da9a3391e 100644 --- a/src/Components/Server/src/ComponentHub.cs +++ b/src/Components/Server/src/ComponentHub.cs @@ -2,13 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.SignalR; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Components.Server { @@ -20,17 +21,23 @@ namespace Microsoft.AspNetCore.Components.Server private static readonly object CircuitKey = new object(); private readonly CircuitFactory _circuitFactory; private readonly CircuitRegistry _circuitRegistry; + private readonly CircuitOptions _options; private readonly ILogger _logger; /// /// Intended for framework use only. Applications should not instantiate /// this class directly. /// - public ComponentHub(IServiceProvider services, ILogger logger) + public ComponentHub( + CircuitFactory circuitFactory, + CircuitRegistry circuitRegistry, + ILogger logger, + IOptions options) { - _circuitFactory = services.GetRequiredService(); - _circuitRegistry = services.GetRequiredService(); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _circuitFactory = circuitFactory; + _circuitRegistry = circuitRegistry; + _options = options.Value; + _logger = logger; } /// @@ -41,6 +48,9 @@ namespace Microsoft.AspNetCore.Components.Server /// /// For unit testing only. /// + // We store the circuit host in Context.Items which is tied to the lifetime of the underlying + // SignalR connection. There's no need to clean this up, it's a non-owning reference and it + // will go away when the connection does. internal CircuitHost CircuitHost { get => (CircuitHost)Context.Items[CircuitKey]; @@ -58,15 +68,60 @@ namespace Microsoft.AspNetCore.Components.Server return Task.CompletedTask; } - CircuitHost = null; - return _circuitRegistry.DisconnectAsync(circuitHost, Context.ConnectionId); + if (exception != null) + { + return _circuitRegistry.DisconnectAsync(circuitHost, Context.ConnectionId); + } + else + { + // The client will gracefully disconnect when using websockets by correctly closing the TCP connection. + // This happens when the user closes a tab, navigates away from the page or reloads the page. + // In these situations we know the user is done with the circuit, so we can get rid of it at that point. + // This is important to be able to more efficiently manage resources, specially memory. + return TerminateCircuitGracefully(circuitHost); + } + } + + private async Task TerminateCircuitGracefully(CircuitHost circuitHost) + { + try + { + Log.CircuitTerminatedGracefully(_logger, circuitHost.CircuitId); + _circuitRegistry.PermanentDisconnect(circuitHost); + await circuitHost.DisposeAsync(); + } + catch (Exception e) + { + Log.UnhandledExceptionInCircuit(_logger, circuitHost.CircuitId, e); + } + + await _circuitRegistry.DisconnectAsync(circuitHost, Context.ConnectionId); } /// /// Intended for framework use only. Applications should not call this method directly. /// - public string StartCircuit(string uriAbsolute, string baseUriAbsolute) + public string StartCircuit(string baseUri, string uri) { + if (CircuitHost != null) + { + Log.CircuitAlreadyInitialized(_logger, CircuitHost.CircuitId); + NotifyClientError(Clients.Caller, $"The circuit host '{CircuitHost.CircuitId}' has already been initialized."); + return null; + } + + if (baseUri == null || + uri == null || + !Uri.IsWellFormedUriString(baseUri, UriKind.Absolute) || + !Uri.IsWellFormedUriString(uri, UriKind.Absolute)) + { + // We do some really minimal validation here to prevent obviously wrong data from getting in + // without duplicating too much logic. + Log.InvalidInputData(_logger); + _ = NotifyClientError(Clients.Caller, $"The uris provided are invalid."); + return null; + } + var circuitClient = new CircuitClientProxy(Clients.Caller, Context.ConnectionId); if (DefaultCircuitFactory.ResolveComponentMetadata(Context.GetHttpContext(), circuitClient).Count == 0) { @@ -79,25 +134,35 @@ namespace Microsoft.AspNetCore.Components.Server return null; } - var circuitHost = _circuitFactory.CreateCircuitHost( - Context.GetHttpContext(), - circuitClient, - uriAbsolute, - baseUriAbsolute); + try + { + var circuitHost = _circuitFactory.CreateCircuitHost( + Context.GetHttpContext(), + circuitClient, + baseUri, + uri, + Context.User); - circuitHost.UnhandledException += CircuitHost_UnhandledException; + circuitHost.UnhandledException += CircuitHost_UnhandledException; - // Fire-and-forget the initialization process, because we can't block the - // SignalR message loop (we'd get a deadlock if any of the initialization - // logic relied on receiving a subsequent message from SignalR), and it will - // take care of its own errors anyway. - _ = circuitHost.InitializeAsync(Context.ConnectionAborted); + // Fire-and-forget the initialization process, because we can't block the + // SignalR message loop (we'd get a deadlock if any of the initialization + // logic relied on receiving a subsequent message from SignalR), and it will + // take care of its own errors anyway. + _ = circuitHost.InitializeAsync(Context.ConnectionAborted); - _circuitRegistry.Register(circuitHost); - - CircuitHost = circuitHost; - - return circuitHost.CircuitId; + // It's safe to *publish* the circuit now because nothing will be able + // to run inside it until after InitializeAsync completes. + _circuitRegistry.Register(circuitHost); + CircuitHost = circuitHost; + return circuitHost.CircuitId; + } + catch (Exception ex) + { + Log.CircuitInitializationFailed(_logger, ex); + NotifyClientError(Clients.Caller, "The circuit failed to initialize."); + return null; + } } /// @@ -109,8 +174,9 @@ namespace Microsoft.AspNetCore.Components.Server if (circuitHost != null) { CircuitHost = circuitHost; + CircuitHost.UnhandledException += CircuitHost_UnhandledException; - circuitHost.InitializeCircuitAfterPrerender(CircuitHost_UnhandledException); + circuitHost.SetCircuitUser(Context.User); circuitHost.SendPendingBatches(); return true; } @@ -123,7 +189,44 @@ namespace Microsoft.AspNetCore.Components.Server /// public void BeginInvokeDotNetFromJS(string callId, string assemblyName, string methodIdentifier, long dotNetObjectId, string argsJson) { - EnsureCircuitHost().BeginInvokeDotNetFromJS(callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson); + if (CircuitHost == null) + { + Log.CircuitHostNotInitialized(_logger); + _ = NotifyClientError(Clients.Caller, "Circuit not initialized."); + return; + } + + _ = CircuitHost.BeginInvokeDotNetFromJS(callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson); + } + + /// + /// Intended for framework use only. Applications should not call this method directly. + /// + public void EndInvokeJSFromDotNet(long asyncHandle, bool succeeded, string arguments) + { + if (CircuitHost == null) + { + Log.CircuitHostNotInitialized(_logger); + _ = NotifyClientError(Clients.Caller, "Circuit not initialized."); + return; + } + + _ = CircuitHost.EndInvokeJSFromDotNet(asyncHandle, succeeded, arguments); + } + + /// + /// Intended for framework use only. Applications should not call this method directly. + /// + public void DispatchBrowserEvent(string eventDescriptor, string eventArgs) + { + if (CircuitHost == null) + { + Log.CircuitHostNotInitialized(_logger); + _ = NotifyClientError(Clients.Caller, "Circuit not initialized."); + return; + } + + _ = CircuitHost.DispatchEvent(eventDescriptor, eventArgs); } /// @@ -131,8 +234,27 @@ namespace Microsoft.AspNetCore.Components.Server /// public void OnRenderCompleted(long renderId, string errorMessageOrNull) { + if (CircuitHost == null) + { + Log.CircuitHostNotInitialized(_logger); + NotifyClientError(Clients.Caller, "Circuit not initialized."); + return; + } + Log.ReceivedConfirmationForBatch(_logger, renderId); - EnsureCircuitHost().Renderer.OnRenderCompleted(renderId, errorMessageOrNull); + CircuitHost.Renderer.OnRenderCompleted(renderId, errorMessageOrNull); + } + + public void OnLocationChanged(string uri, bool intercepted) + { + if (CircuitHost == null) + { + Log.CircuitHostNotInitialized(_logger); + NotifyClientError(Clients.Caller, "Circuit not initialized."); + return; + } + + _ = CircuitHost.OnLocationChangedAsync(uri, intercepted); } private async void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e) @@ -143,7 +265,17 @@ namespace Microsoft.AspNetCore.Components.Server try { Log.UnhandledExceptionInCircuit(_logger, circuitId, (Exception)e.ExceptionObject); - await circuitHost.Client.SendAsync("JS.Error", e.ExceptionObject); + if (_options.DetailedErrors) + { + await NotifyClientError(circuitHost.Client, e.ExceptionObject.ToString()); + } + else + { + var message = $"There was an unhandled exception on the current circuit, so this circuit will be terminated. For more details turn on " + + $"detailed exceptions in '{typeof(CircuitOptions).Name}.{nameof(CircuitOptions.DetailedErrors)}'"; + + await NotifyClientError(circuitHost.Client, message); + } // We generally can't abort the connection here since this is an async // callback. The Hub has already been torn down. We'll rely on the @@ -155,17 +287,8 @@ namespace Microsoft.AspNetCore.Components.Server } } - private CircuitHost EnsureCircuitHost() - { - var circuitHost = CircuitHost; - if (circuitHost == null) - { - var message = $"The {nameof(CircuitHost)} is null. This is due to an exception thrown during initialization."; - throw new InvalidOperationException(message); - } - - return circuitHost; - } + private static Task NotifyClientError(IClientProxy client, string error) => + client.SendAsync("JS.Error", error); private static class Log { @@ -181,6 +304,21 @@ namespace Microsoft.AspNetCore.Components.Server private static readonly Action _failedToTransmitException = LoggerMessage.Define(LogLevel.Debug, new EventId(4, "FailedToTransmitException"), "Failed to transmit exception to client in circuit {CircuitId}"); + private static readonly Action _circuitAlreadyInitialized = + LoggerMessage.Define(LogLevel.Debug, new EventId(5, "CircuitAlreadyInitialized"), "The circuit host '{CircuitId}' has already been initialized"); + + private static readonly Action _circuitHostNotInitialized = + LoggerMessage.Define(LogLevel.Debug, new EventId(6, "CircuitHostNotInitialized"), "Call to '{CallSite}' received before the circuit host initialization"); + + private static readonly Action _circuitTerminatedGracefully = + LoggerMessage.Define(LogLevel.Debug, new EventId(7, "CircuitTerminatedGracefully"), "Circuit '{CircuitId}' terminated gracefully"); + + private static readonly Action _invalidInputData = + LoggerMessage.Define(LogLevel.Debug, new EventId(8, "InvalidInputData"), "Call to '{CallSite}' received invalid input data"); + + private static readonly Action _circuitInitializationFailed = + LoggerMessage.Define(LogLevel.Debug, new EventId(9, "CircuitInitializationFailed"), "Circuit initialization failed"); + public static void NoComponentsRegisteredInEndpoint(ILogger logger, string endpointDisplayName) { _noComponentsRegisteredInEndpoint(logger, endpointDisplayName, null); @@ -200,6 +338,16 @@ namespace Microsoft.AspNetCore.Components.Server { _failedToTransmitException(logger, circuitId, transmissionException); } + + public static void CircuitAlreadyInitialized(ILogger logger, string circuitId) => _circuitAlreadyInitialized(logger, circuitId, null); + + public static void CircuitHostNotInitialized(ILogger logger, [CallerMemberName] string callSite = "") => _circuitHostNotInitialized(logger, callSite, null); + + public static void CircuitTerminatedGracefully(ILogger logger, string circuitId) => _circuitTerminatedGracefully(logger, circuitId, null); + + public static void InvalidInputData(ILogger logger, [CallerMemberName] string callSite = "") => _invalidInputData(logger, callSite, null); + + public static void CircuitInitializationFailed(ILogger logger, Exception exception) => _circuitInitializationFailed(logger, exception); } } } diff --git a/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs b/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs index 826410e0d1..50bf75132d 100644 --- a/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs +++ b/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs @@ -63,20 +63,14 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(); - // We explicitly take over the prerendering and components services here. - // We can't have two separate component implementations coexisting at the - // same time, so when you register components (Circuits) it takes over - // all the abstractions. - services.AddScoped(); - - // Standard razor component services implementations + // Standard blazor hosting services implementations // // These intentionally replace the non-interactive versions included in MVC. - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.TryAddEnumerable(ServiceDescriptor.Singleton, CircuitOptionsJSInteropDetailedErrorsConfiguration>()); diff --git a/src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj b/src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj index 734023b0f5..3f87bd43af 100644 --- a/src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj +++ b/src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -8,18 +8,19 @@ true true CS0436;$(NoWarn) - $(DefineConstants);MESSAGEPACK_INTERNAL + $(DefineConstants);MESSAGEPACK_INTERNAL;COMPONENTS_SERVER - + + @@ -28,6 +29,7 @@ + diff --git a/src/Components/Server/src/Prerendering/ComponentPrerenderResult.cs b/src/Components/Server/src/Prerendering/ComponentPrerenderResult.cs deleted file mode 100644 index 3a8aa93632..0000000000 --- a/src/Components/Server/src/Prerendering/ComponentPrerenderResult.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.Collections.Generic; -using System.IO; - -namespace Microsoft.AspNetCore.Components.Server -{ - /// - /// Represents the result of a prerendering an . - /// - public sealed class ComponentPrerenderResult - { - private readonly IEnumerable _result; - - internal ComponentPrerenderResult(IEnumerable result) - { - _result = result; - } - - /// - /// Writes the prerendering result to the given . - /// - /// The the results will be written to. - public void WriteTo(TextWriter writer) - { - foreach (var element in _result) - { - writer.Write(element); - } - } - } -} diff --git a/src/Components/Server/src/Prerendering/ComponentPrerenderingContext.cs b/src/Components/Server/src/Prerendering/ComponentPrerenderingContext.cs deleted file mode 100644 index 436c27b31a..0000000000 --- a/src/Components/Server/src/Prerendering/ComponentPrerenderingContext.cs +++ /dev/null @@ -1,29 +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.Http; - -namespace Microsoft.AspNetCore.Components.Server -{ - /// - /// The context for prerendering a component. - /// - public class ComponentPrerenderingContext - { - /// - /// Gets or sets the component type. - /// - public Type ComponentType { get; set; } - - /// - /// Gets or sets the parameters for the component. - /// - public ParameterCollection Parameters { get; set; } - - /// - /// Gets or sets the in which the prerendering has been initiated. - /// - public HttpContext Context { get; set; } - } -} diff --git a/src/Components/Server/src/Prerendering/IComponentPrerenderer.cs b/src/Components/Server/src/Prerendering/IComponentPrerenderer.cs deleted file mode 100644 index a8513af17d..0000000000 --- a/src/Components/Server/src/Prerendering/IComponentPrerenderer.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.Server -{ - /// - /// Prerrenders instances. - /// - public interface IComponentPrerenderer - { - /// - /// Prerrenders the component . - /// - /// The context in which the prerrendering is happening. - /// that will complete when the prerendering is done. - Task PrerenderComponentAsync(ComponentPrerenderingContext context); - } -} diff --git a/src/Components/Server/test/Circuits/CircuitHostTest.cs b/src/Components/Server/test/Circuits/CircuitHostTest.cs index 8004c5cd08..58803a56b2 100644 --- a/src/Components/Server/test/Circuits/CircuitHostTest.cs +++ b/src/Components/Server/test/Circuits/CircuitHostTest.cs @@ -275,7 +275,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits public bool DidCallDispose { get; private set; } public void Attach(RenderHandle renderHandle) { } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => Task.CompletedTask; public void Dispose() diff --git a/src/Components/Server/test/Circuits/CircuitPrerendererTest.cs b/src/Components/Server/test/Circuits/CircuitPrerendererTest.cs deleted file mode 100644 index 2ecf8a7fab..0000000000 --- a/src/Components/Server/test/Circuits/CircuitPrerendererTest.cs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text.Json; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Server.Circuits; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Server.Tests.Circuits -{ - public class CircuitPrerendererTest - { - private static readonly Regex ContentWrapperRegex = new Regex( - "(?.*)", - RegexOptions.Compiled | RegexOptions.Singleline, TimeSpan.FromSeconds(1)); // Treat the entire input string as a single line - - private static readonly Regex CircuitInfoRegex = new Regex( - ".*", - RegexOptions.Compiled | RegexOptions.Singleline, TimeSpan.FromSeconds(1)); // Treat the entire input string as a single line - - // Because CircuitPrerenderer is a point of integration with HttpContext, - // it's not a good candidate for unit testing. The majority of prerendering - // unit tests should be elsewhere in HtmlRendererTests inside the - // Microsoft.AspNetCore.Components.Tests projects. - // - // The only unit tests added here should specifically be about how we're - // interacting with the HttpContext for configuring the prerenderer. - - [Fact] - public async Task ExtractsUriFromHttpContext_EmptyPathBase() - { - // Arrange - var circuitFactory = new TestCircuitFactory(); - var circuitRegistry = new CircuitRegistry( - Options.Create(new CircuitOptions()), - Mock.Of>(), - TestCircuitIdFactory.CreateTestFactory()); - var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry); - var httpContext = new DefaultHttpContext(); - var httpRequest = httpContext.Request; - httpRequest.Scheme = "https"; - httpRequest.Host = new HostString("example.com", 1234); - httpRequest.Path = "/some/path"; - - var prerenderingContext = new ComponentPrerenderingContext - { - ComponentType = typeof(UriDisplayComponent), - Parameters = ParameterCollection.Empty, - Context = httpContext - }; - - // Act - var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext); - // Assert - Assert.Equal(string.Join("", new[] - { - "The current URI is ", - "https://example.com:1234/some/path", - " within base URI ", - "https://example.com:1234/" - }), GetUnwrappedContent(result)); - } - - private string GetUnwrappedContent(ComponentPrerenderResult rawResult) - { - var writer = new StringWriter(); - rawResult.WriteTo(writer); - return ContentWrapperRegex.Match(writer.ToString()) - .Groups["content"].Value - .Replace("\r\n","\n"); - } - - private JsonDocument GetUnwrappedCircuitInfo(ComponentPrerenderResult rawResult) - { - var writer = new StringWriter(); - rawResult.WriteTo(writer); - var circuitInfo = CircuitInfoRegex.Match(writer.ToString()).Groups["info"].Value; - - return JsonDocument.Parse(circuitInfo); - } - - [Fact] - public async Task ExtractsUriFromHttpContext_NonemptyPathBase() - { - // Arrange - var circuitFactory = new TestCircuitFactory(); - var circuitRegistry = new CircuitRegistry( - Options.Create(new CircuitOptions()), - Mock.Of>(), - TestCircuitIdFactory.CreateTestFactory()); - var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry); - var httpContext = new DefaultHttpContext(); - var httpRequest = httpContext.Request; - httpRequest.Scheme = "https"; - httpRequest.Host = new HostString("example.com", 1234); - httpRequest.PathBase = "/my/dir"; - httpRequest.Path = "/some/path"; - - var prerenderingContext = new ComponentPrerenderingContext - { - ComponentType = typeof(UriDisplayComponent), - Parameters = ParameterCollection.Empty, - Context = httpContext - }; - - // Act - var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext); - - // Assert - Assert.Equal(string.Join("", new[] - { - "The current URI is ", - "https://example.com:1234/my/dir/some/path", - " within base URI ", - "https://example.com:1234/my/dir/" - }), GetUnwrappedContent(result)); - } - - [Fact] - public async Task ReplacesDashesWithDots_WhenTheyAppearInPairs() - { - // Arrange - var circuitFactory = new TestCircuitFactory(() => "--1234--"); - var circuitRegistry = new CircuitRegistry( - Options.Create(new CircuitOptions()), - Mock.Of>(), - TestCircuitIdFactory.CreateTestFactory()); - var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry); - var httpContext = new DefaultHttpContext(); - var httpRequest = httpContext.Request; - httpRequest.Scheme = "https"; - httpRequest.Host = new HostString("example.com", 1234); - httpRequest.Path = "/some/path"; - - var prerenderingContext = new ComponentPrerenderingContext - { - ComponentType = typeof(UriDisplayComponent), - Parameters = ParameterCollection.Empty, - Context = httpContext - }; - - // Act - var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext); - - // Assert - Assert.Equal("..1234..", GetUnwrappedCircuitInfo(result).RootElement.GetProperty("circuitId").GetString()); - } - - [Fact] - public async Task DisposesCircuitScopeEvenIfPrerenderingThrows() - { - // Arrange - var circuitFactory = new MockServiceScopeCircuitFactory(); - var circuitRegistry = new CircuitRegistry( - Options.Create(new CircuitOptions()), - Mock.Of>(), - TestCircuitIdFactory.CreateTestFactory()); - var httpContext = new DefaultHttpContext(); - var prerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry); - var prerenderingContext = new ComponentPrerenderingContext - { - ComponentType = typeof(ThrowExceptionComponent), - Parameters = ParameterCollection.Empty, - Context = httpContext - }; - - // Act - await Assert.ThrowsAsync(async () => - await prerenderer.PrerenderComponentAsync(prerenderingContext)); - - // Assert - circuitFactory.MockServiceScope.Verify(scope => scope.Dispose(), Times.Once()); - } - - class TestCircuitFactory : CircuitFactory - { - private readonly Func _circuitIdFactory; - - public TestCircuitFactory(Func circuitIdFactory = null) - { - _circuitIdFactory = circuitIdFactory ?? (() => Guid.NewGuid().ToString()); - } - - public override CircuitHost CreateCircuitHost(HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute) - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddScoped(_ => - { - var uriHelper = new RemoteUriHelper(NullLogger.Instance); - uriHelper.InitializeState(uriAbsolute, baseUriAbsolute); - return uriHelper; - }); - var serviceScope = serviceCollection.BuildServiceProvider().CreateScope(); - return TestCircuitHost.Create(_circuitIdFactory(), serviceScope); - } - } - - class MockServiceScopeCircuitFactory : CircuitFactory - { - public Mock MockServiceScope { get; } - = new Mock(); - - public override CircuitHost CreateCircuitHost(HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute) - { - return TestCircuitHost.Create(Guid.NewGuid().ToString(), MockServiceScope.Object); - } - } - - class UriDisplayComponent : IComponent - { - private RenderHandle _renderHandle; - - [Inject] IUriHelper UriHelper { get; set; } - - public void Attach(RenderHandle renderHandle) - { - _renderHandle = renderHandle; - } - - public Task SetParametersAsync(ParameterCollection parameters) - { - _renderHandle.Render(builder => - { - builder.AddContent(0, "The current URI is "); - builder.AddContent(1, UriHelper.GetAbsoluteUri()); - builder.AddContent(2, " within base URI "); - builder.AddContent(3, UriHelper.GetBaseUri()); - }); - - return Task.CompletedTask; - } - } - - class ThrowExceptionComponent : IComponent - { - public void Attach(RenderHandle renderHandle) - => throw new InvalidTimeZoneException(); - - public Task SetParametersAsync(ParameterCollection parameters) - => Task.CompletedTask; - } - } -} diff --git a/src/Components/Server/test/Circuits/FixedAuthenticationStateProviderTest.cs b/src/Components/Server/test/Circuits/FixedAuthenticationStateProviderTest.cs deleted file mode 100644 index e1a538c9ab..0000000000 --- a/src/Components/Server/test/Circuits/FixedAuthenticationStateProviderTest.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 System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Server.Circuits; -using Microsoft.AspNetCore.Http; -using Xunit; - -namespace Microsoft.AspNetCore.Components.Server.Tests.Circuits -{ - public class FixedAuthenticationStateProviderTest - { - [Fact] - public async Task CannotProvideAuthenticationStateBeforeInitialization() - { - await Assert.ThrowsAsync(() => - new FixedAuthenticationStateProvider() - .GetAuthenticationStateAsync()); - } - - [Fact] - public async Task SuppliesAuthenticationStateWithFixedUser() - { - // Arrange - var user = new ClaimsPrincipal(); - var provider = new FixedAuthenticationStateProvider(); - provider.Initialize(user); - - // Act - var authenticationState = await provider.GetAuthenticationStateAsync(); - - // Assert - Assert.NotNull(authenticationState); - Assert.Same(user, authenticationState.User); - } - } -} diff --git a/src/Components/Server/test/Circuits/RemoteRendererTest.cs b/src/Components/Server/test/Circuits/RemoteRendererTest.cs index bfdd02fd1c..ffb913544a 100644 --- a/src/Components/Server/test/Circuits/RemoteRendererTest.cs +++ b/src/Components/Server/test/Circuits/RemoteRendererTest.cs @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering component.TriggerRender(); // Assert - Assert.Equal(2, renderer.PendingRenderBatches.Count); + Assert.Equal(2, renderer.UnacknowledgedRenderBatches.Count); } [Fact] @@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering } [Fact] - public async Task OnRenderCompletedAsync_ThrowsWhenNoBatchesAreQueued() + public async Task OnRenderCompletedAsync_DoesNotThrowWhenReceivedDuplicateAcks() { // Arrange var serviceProvider = new ServiceCollection().BuildServiceProvider(); @@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering // This produces the initial batch (id = 2) var result = await renderer.RenderComponentAsync( - ParameterCollection.FromDictionary(new Dictionary + ParameterView.FromDictionary(new Dictionary { [nameof(AutoParameterTestComponent.Content)] = initialContent, [nameof(AutoParameterTestComponent.Trigger)] = trigger @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering }; // This produces an additional batch (id = 3) trigger.TriggerRender(); - var originallyQueuedBatches = renderer.PendingRenderBatches.Count; + var originallyQueuedBatches = renderer.UnacknowledgedRenderBatches.Count; // Act offlineClient.Transfer(onlineClient.Object, "new-connection"); @@ -163,19 +163,22 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering exceptions.Add(e); }; - // Pretend that we missed the ack for the initial batch + // Receive the ack for the intial batch renderer.OnRenderCompleted(2, null); + // Receive the ack for the second batch renderer.OnRenderCompleted(3, null); + firstBatchTCS.SetResult(null); secondBatchTCS.SetResult(null); + // Repeat the ack for the third batch renderer.OnRenderCompleted(3, null); // Assert - var exception = Assert.Single(exceptions); + Assert.Empty(exceptions); } [Fact] - public async Task ThrowsIfWeReceiveAnOutOfSequenceClientAcknowledge() + public async Task OnRenderCompletedAsync_DoesNotThrowWhenThereAreNoPendingBatchesToAck() { // Arrange var serviceProvider = new ServiceCollection().BuildServiceProvider(); @@ -199,7 +202,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering // This produces the initial batch (id = 2) var result = await renderer.RenderComponentAsync( - ParameterCollection.FromDictionary(new Dictionary + ParameterView.FromDictionary(new Dictionary { [nameof(AutoParameterTestComponent.Content)] = initialContent, [nameof(AutoParameterTestComponent.Trigger)] = trigger @@ -212,7 +215,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering }; // This produces an additional batch (id = 3) trigger.TriggerRender(); - var originallyQueuedBatches = renderer.PendingRenderBatches.Count; + var originallyQueuedBatches = renderer.UnacknowledgedRenderBatches.Count; // Act offlineClient.Transfer(onlineClient.Object, "new-connection"); @@ -223,13 +226,133 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering exceptions.Add(e); }; + // Receive the ack for the intial batch + renderer.OnRenderCompleted(2, null); + // Receive the ack for the second batch + renderer.OnRenderCompleted(2, null); + + firstBatchTCS.SetResult(null); + secondBatchTCS.SetResult(null); + // Repeat the ack for the third batch + renderer.OnRenderCompleted(3, null); + + // Assert + Assert.Empty(exceptions); + } + + [Fact] + public async Task ConsumesAllPendingBatchesWhenReceivingAHigherSequenceBatchId() + { + // Arrange + var serviceProvider = new ServiceCollection().BuildServiceProvider(); + var firstBatchTCS = new TaskCompletionSource(); + var secondBatchTCS = new TaskCompletionSource(); + var renderIds = new List(); + + var onlineClient = new Mock(); + onlineClient.Setup(c => c.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((string name, object[] value, CancellationToken token) => renderIds.Add((long)value[1])) + .Returns((n, v, t) => (long)v[1] == 2 ? firstBatchTCS.Task : secondBatchTCS.Task); + + var renderer = GetRemoteRenderer(serviceProvider, new CircuitClientProxy(onlineClient.Object, "online-client")); + RenderFragment initialContent = (builder) => + { + builder.OpenElement(0, "my element"); + builder.AddContent(1, "some text"); + builder.CloseElement(); + }; + var trigger = new Trigger(); + + // This produces the initial batch (id = 2) + var result = await renderer.RenderComponentAsync( + ParameterView.FromDictionary(new Dictionary + { + [nameof(AutoParameterTestComponent.Content)] = initialContent, + [nameof(AutoParameterTestComponent.Trigger)] = trigger + })); + trigger.Component.Content = (builder) => + { + builder.OpenElement(0, "offline element"); + builder.AddContent(1, "offline text"); + builder.CloseElement(); + }; + // This produces an additional batch (id = 3) + trigger.TriggerRender(); + var originallyQueuedBatches = renderer.UnacknowledgedRenderBatches.Count; + + // Act + var exceptions = new List(); + renderer.UnhandledException += (sender, e) => + { + exceptions.Add(e); + }; + // Pretend that we missed the ack for the initial batch renderer.OnRenderCompleted(3, null); firstBatchTCS.SetResult(null); secondBatchTCS.SetResult(null); + // Assert + Assert.Empty(exceptions); + Assert.Empty(renderer.UnacknowledgedRenderBatches); + } + + [Fact] + public async Task ThrowsIfWeReceivedAnAcknowledgeForANeverProducedBatch() + { + // Arrange + var serviceProvider = new ServiceCollection().BuildServiceProvider(); + var firstBatchTCS = new TaskCompletionSource(); + var secondBatchTCS = new TaskCompletionSource(); + var renderIds = new List(); + + var onlineClient = new Mock(); + onlineClient.Setup(c => c.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((string name, object[] value, CancellationToken token) => renderIds.Add((long)value[1])) + .Returns((n, v, t) => (long)v[1] == 2 ? firstBatchTCS.Task : secondBatchTCS.Task); + + var renderer = GetRemoteRenderer(serviceProvider, new CircuitClientProxy(onlineClient.Object, "online-client")); + RenderFragment initialContent = (builder) => + { + builder.OpenElement(0, "my element"); + builder.AddContent(1, "some text"); + builder.CloseElement(); + }; + var trigger = new Trigger(); + + // This produces the initial batch (id = 2) + var result = await renderer.RenderComponentAsync( + ParameterView.FromDictionary(new Dictionary + { + [nameof(AutoParameterTestComponent.Content)] = initialContent, + [nameof(AutoParameterTestComponent.Trigger)] = trigger + })); + trigger.Component.Content = (builder) => + { + builder.OpenElement(0, "offline element"); + builder.AddContent(1, "offline text"); + builder.CloseElement(); + }; + // This produces an additional batch (id = 3) + trigger.TriggerRender(); + var originallyQueuedBatches = renderer.UnacknowledgedRenderBatches.Count; + + // Act + var exceptions = new List(); + renderer.UnhandledException += (sender, e) => + { + exceptions.Add(e); + }; + + renderer.OnRenderCompleted(4, null); + firstBatchTCS.SetResult(null); + secondBatchTCS.SetResult(null); + // Assert var exception = Assert.Single(exceptions); + Assert.Equal( + "Received an acknowledgement for batch with id '4' when the last batch produced was '3'.", + exception.Message); } [Fact] @@ -243,13 +366,13 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering new CircuitClientProxy()); // Act - var first = await renderer.RenderComponentAsync(ParameterCollection.Empty); - var second = await renderer.RenderComponentAsync(ParameterCollection.Empty); + var first = await renderer.RenderComponentAsync(ParameterView.Empty); + var second = await renderer.RenderComponentAsync(ParameterView.Empty); // Assert Assert.Equal(0, first.ComponentId); Assert.Equal(1, second.ComponentId); - Assert.Equal(2, renderer.PendingRenderBatches.Count); + Assert.Equal(2, renderer.UnacknowledgedRenderBatches.Count); } private RemoteRenderer GetRemoteRenderer(IServiceProvider serviceProvider, CircuitClientProxy circuitClientProxy) @@ -304,7 +427,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering return Task.CompletedTask; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { TriggerRender(); return Task.CompletedTask; @@ -330,7 +453,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering _renderHandle = renderHandle; } - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) { Content = parameters.GetValueOrDefault(nameof(Content)); Trigger ??= parameters.GetValueOrDefault(nameof(Trigger)); diff --git a/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs b/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs index 3ccba9ff5a..b52862bb2d 100644 --- a/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs +++ b/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Server.Circuits; +using Microsoft.AspNetCore.Components.Web.Rendering; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using System; @@ -153,7 +154,7 @@ namespace Microsoft.AspNetCore.Components.Server RenderTreeEdit.UpdateMarkup(108, 109), RenderTreeEdit.RemoveAttribute(110, "Some removed attribute"), // To test deduplication }; - var editsBuilder = new ArrayBuilder(); + var editsBuilder = new RenderTree.ArrayBuilder(); editsBuilder.Append(edits, 0, edits.Length); var editsSegment = editsBuilder.ToSegment(1, edits.Length); // Skip first to show offset is respected var bytes = Serialize(new RenderBatch( @@ -373,7 +374,7 @@ namespace Microsoft.AspNetCore.Components.Server public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } diff --git a/src/Components/Server/test/Circuits/ServerAuthenticationStateProviderTest.cs b/src/Components/Server/test/Circuits/ServerAuthenticationStateProviderTest.cs new file mode 100644 index 0000000000..6411c25f6b --- /dev/null +++ b/src/Components/Server/test/Circuits/ServerAuthenticationStateProviderTest.cs @@ -0,0 +1,49 @@ +// Copyright (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.Components.Server.Circuits; +using Xunit; + +namespace Microsoft.AspNetCore.Components.Server.Tests.Circuits +{ + public class ServerAuthenticationStateProviderTest + { + [Fact] + public async Task CannotProvideAuthenticationStateBeforeInitialization() + { + await Assert.ThrowsAsync(() => + new ServerAuthenticationStateProvider() + .GetAuthenticationStateAsync()); + } + + [Fact] + public async Task SuppliesAuthenticationStateWithFixedUser() + { + // Arrange + var user = new ClaimsPrincipal(); + var provider = new ServerAuthenticationStateProvider(); + + // Act 1 + var expectedAuthenticationState1 = new AuthenticationState(user); + provider.SetAuthenticationState(Task.FromResult(expectedAuthenticationState1)); + + // Assert 1 + var actualAuthenticationState1 = await provider.GetAuthenticationStateAsync(); + Assert.NotNull(actualAuthenticationState1); + Assert.Same(expectedAuthenticationState1, actualAuthenticationState1); + + // Act 2: Show we can update it further + var expectedAuthenticationState2 = new AuthenticationState(user); + provider.SetAuthenticationState(Task.FromResult(expectedAuthenticationState2)); + + // Assert 2 + var actualAuthenticationState2 = await provider.GetAuthenticationStateAsync(); + Assert.NotNull(actualAuthenticationState2); + Assert.NotSame(actualAuthenticationState1, actualAuthenticationState2); + Assert.Same(expectedAuthenticationState2, actualAuthenticationState2); + } + } +} diff --git a/src/Components/Server/test/Circuits/TestCircuitHost.cs b/src/Components/Server/test/Circuits/TestCircuitHost.cs index 326675cfe0..f8f5996d95 100644 --- a/src/Components/Server/test/Circuits/TestCircuitHost.cs +++ b/src/Components/Server/test/Circuits/TestCircuitHost.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits { internal class TestCircuitHost : CircuitHost { - private TestCircuitHost(string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IList descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger) + private TestCircuitHost(string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IReadOnlyList descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger) : base(circuitId, scope, client, rendererRegistry, renderer, descriptors, jsRuntime, circuitHandlers, logger) { } @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits serviceScope = serviceScope ?? Mock.Of(); clientProxy = clientProxy ?? new CircuitClientProxy(Mock.Of(), Guid.NewGuid().ToString()); var renderRegistry = new RendererRegistry(); - var jsRuntime = new RemoteJSRuntime(Options.Create(new CircuitOptions())); + var jsRuntime = new RemoteJSRuntime(Options.Create(new CircuitOptions()), Mock.Of>()); if (remoteRenderer == null) { diff --git a/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs b/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs index 456d9facd7..cba13e8581 100644 --- a/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs +++ b/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs @@ -2,8 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Diagnostics; +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Moq; @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Components.Server.Tests .UseRouting() .UseEndpoints(endpoints => { - endpoints.MapBlazorHub(dispatchOptions => called = true); + endpoints.MapBlazorHub("app", dispatchOptions => called = true); }).Build(); // Assert @@ -68,5 +68,18 @@ namespace Microsoft.AspNetCore.Components.Server.Tests return new ApplicationBuilder(serviceProvder); } + + private class MyComponent : IComponent + { + public void Attach(RenderHandle renderHandle) + { + throw new System.NotImplementedException(); + } + + public Task SetParametersAsync(ParameterView parameters) + { + throw new System.NotImplementedException(); + } + } } } diff --git a/src/Components/Components/src/RenderTree/ArrayBuilder.cs b/src/Components/Shared/src/ArrayBuilder.cs similarity index 87% rename from src/Components/Components/src/RenderTree/ArrayBuilder.cs rename to src/Components/Shared/src/ArrayBuilder.cs index 9d3e71993a..b0f203fdcc 100644 --- a/src/Components/Components/src/RenderTree/ArrayBuilder.cs +++ b/src/Components/Shared/src/ArrayBuilder.cs @@ -6,7 +6,11 @@ using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; +#if COMPONENTS_SERVER +namespace Microsoft.AspNetCore.Components.Web.Rendering +#else namespace Microsoft.AspNetCore.Components.RenderTree +#endif { /// /// Implements a list that uses an array of objects to store the elements. @@ -154,22 +158,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree _itemsInUse = 0; } - /// - /// Produces an structure describing the current contents. - /// - /// The . - public ArrayRange ToRange() - => new ArrayRange(_items, _itemsInUse); - - /// - /// Produces an structure describing the selected contents. - /// - /// The index of the first item in the segment. - /// One plus the index of the last item in the segment. - /// The . - public ArrayBuilderSegment ToSegment(int fromIndexInclusive, int toIndexExclusive) - => new ArrayBuilderSegment(this, fromIndexInclusive, toIndexExclusive - fromIndexInclusive); - private void GrowBuffer(int desiredCapacity) { var newCapacity = Math.Max(desiredCapacity, _minCapacity); diff --git a/src/Components/Shared/test/AssertFrame.cs b/src/Components/Shared/test/AssertFrame.cs index e1a412500e..1fb2debbf2 100644 --- a/src/Components/Shared/test/AssertFrame.cs +++ b/src/Components/Shared/test/AssertFrame.cs @@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers Assert.Equal(attributeValue, frame.AttributeValue); } - public static void Attribute(RenderTreeFrame frame, string attributeName, Action attributeEventHandlerValue, int? sequence = null) + public static void Attribute(RenderTreeFrame frame, string attributeName, Action attributeEventHandlerValue, int? sequence = null) { AssertFrame.Attribute(frame, attributeName, sequence); Assert.Equal(attributeEventHandlerValue, frame.AttributeValue); @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers Assert.True(string.IsNullOrWhiteSpace(frame.TextContent)); } - public static void ElementReferenceCapture(RenderTreeFrame frame, Action action, int? sequence = null) + public static void ElementReferenceCapture(RenderTreeFrame frame, Action action, int? sequence = null) { Assert.Equal(RenderTreeFrameType.ElementReferenceCapture, frame.FrameType); Assert.Same(action, frame.ElementReferenceCaptureAction); diff --git a/src/Components/Shared/test/AutoRenderComponent.cs b/src/Components/Shared/test/AutoRenderComponent.cs index 8ebe6034bb..c446034950 100644 --- a/src/Components/Shared/test/AutoRenderComponent.cs +++ b/src/Components/Shared/test/AutoRenderComponent.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers _renderHandle = renderHandle; } - public virtual Task SetParametersAsync(ParameterCollection parameters) + public virtual Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); TriggerRender(); diff --git a/src/Components/Shared/test/IComponentExtensions.cs b/src/Components/Shared/test/IComponentExtensions.cs index 34b7528548..93d48ee9a4 100644 --- a/src/Components/Shared/test/IComponentExtensions.cs +++ b/src/Components/Shared/test/IComponentExtensions.cs @@ -1,10 +1,9 @@ // Copyright (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.RenderTree; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.RenderTree; namespace Microsoft.AspNetCore.Components.Test.Helpers { @@ -14,27 +13,7 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers this IComponent component, Dictionary parameters) { - component.SetParametersAsync(DictionaryToParameterCollection(parameters)); - } - - private static ParameterCollection DictionaryToParameterCollection( - IDictionary parameters) - { - var builder = new RenderTreeBuilder(new TestRenderer()); - builder.OpenComponent(0); - foreach (var pair in parameters) - { - builder.AddAttribute(0, pair.Key, pair.Value); - } - builder.CloseElement(); - - return new ParameterCollection(builder.GetFrames().Array, 0); - } - - private abstract class AbstractComponent : IComponent - { - public abstract void Attach(RenderHandle renderHandle); - public abstract Task SetParametersAsync(ParameterCollection parameters); + component.SetParametersAsync(ParameterView.FromDictionary(parameters)); } } } diff --git a/src/Components/Shared/test/TestRenderer.cs b/src/Components/Shared/test/TestRenderer.cs index 944be7ec87..d5ce07bf4b 100644 --- a/src/Components/Shared/test/TestRenderer.cs +++ b/src/Components/Shared/test/TestRenderer.cs @@ -48,22 +48,22 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers public new int AssignRootComponentId(IComponent component) => base.AssignRootComponentId(component); - public void RenderRootComponent(int componentId, ParameterCollection? parameters = default) + public void RenderRootComponent(int componentId, ParameterView? parameters = default) { - var task = Dispatcher.InvokeAsync(() => base.RenderRootComponentAsync(componentId, parameters ?? ParameterCollection.Empty)); + var task = Dispatcher.InvokeAsync(() => base.RenderRootComponentAsync(componentId, parameters ?? ParameterView.Empty)); UnwrapTask(task); } public new Task RenderRootComponentAsync(int componentId) => Dispatcher.InvokeAsync(() => base.RenderRootComponentAsync(componentId)); - public new Task RenderRootComponentAsync(int componentId, ParameterCollection parameters) + public new Task RenderRootComponentAsync(int componentId, ParameterView parameters) => Dispatcher.InvokeAsync(() => base.RenderRootComponentAsync(componentId, parameters)); - public Task DispatchEventAsync(ulong eventHandlerId, UIEventArgs args) + public Task DispatchEventAsync(ulong eventHandlerId, EventArgs args) => Dispatcher.InvokeAsync(() => base.DispatchEventAsync(eventHandlerId, null, args)); - public new Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo eventFieldInfo, UIEventArgs args) + public new Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo eventFieldInfo, EventArgs args) => Dispatcher.InvokeAsync(() => base.DispatchEventAsync(eventHandlerId, eventFieldInfo, args)); private static Task UnwrapTask(Task task) diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index 215af6db47..a79de53cec 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -1,15 +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=48)}([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(6),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]-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(42),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(43);!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 P(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1);default:throw new Error("Unknown transport: "+e+".")}},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",n+=-1===t?"":e.substring(t)},e}();var W=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new q,this.transportResult=new q,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new q),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 q,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;o0&&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(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 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(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}(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(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])){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 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",n+=-1===t?"":e.substring(t)},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(49),o=n(50),i=n(51);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 P(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 x(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 M(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 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):M(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):M(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):L(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):L(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):M(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):M(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):L(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):L(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 W(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(8))},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(21),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(18);i.inherits=n(14);var a=n(34),s=n(39);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";Object.defineProperty(t,"__esModule",{value:!0});var r=n(25),o=n(12),i={};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(t);if(!r)throw new Error("Could not find any element matching selector '"+t+"'.");a(e,o.toLogicalElement(r,!0),n)},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),s=r.count(o),c=t.referenceFrames(),u=r.values(c),l=t.diffReader,f=0;f0&&!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(5),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";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){for(var n=[],r=2;r1)for(var n=1;n0&&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.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]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]=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(53);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(54),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 x="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function P(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(x&&e[x]){var t;if("function"!=typeof(t=e[x]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,x,{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(M,t,e))}function M(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?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!==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===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(35).EventEmitter},function(e,t,n){"use strict";var r=n(21);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(60).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(21);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(18);u.inherits=n(14);var l={deprecate:n(63)},f=n(36),h=n(13).Buffer,p=o.Uint8Array||function(){};var d,g=n(37);function y(){}function v(e,t){s=s||n(9),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(9),!(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(17),n(61).setImmediate,n(8))},function(e,t,n){"use strict";e.exports=a;var r=n(9),o=n(18);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.length0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=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(5).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 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(5).Buffer)},,,,,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;n0&&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-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 s(){return c.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(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,s=1,a=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;s=2,a/=2,c/=2,n/=2}function u(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(o){var l=-1;for(i=n;ia&&(n=a-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 s=0;s>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],s=e[o+2],128==(192&i)&&128==(192&s)&&(c=(15&u)<<12|(63&i)<<6|63&s)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=e[o+1],s=e[o+2],a=e[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(c=(15&u)<<18|(63&i)<<12|(63&s)<<6|63&a)>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),s=(n>>>=0)-(t>>>=0),a=Math.min(i,s),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 M(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 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):M(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):M(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):L(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):L(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,s=1,a=0;for(this[t]=255&e;++i>0)-a&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,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},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):M(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):M(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):L(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):L(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(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(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(10))},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";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(9);var r=n(26),o=n(16),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(t);if(!r)throw new Error("Could not find any element matching selector '"+t+"'.");a(e,o.toLogicalElement(r,!0),n)},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),c=r.count(o),u=t.referenceFrames(),l=r.values(u),f=t.diffReader,h=0;h=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){var r=n(5),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";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){for(var n=[],r=2;r0&&!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&&(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 s=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 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,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 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 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=a(h);l=!0;for(var t=u.length;t;){for(c=u,u=[];++f1)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]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,c=this._offset(n),u=r-n,l=u,f=a&&t||0,h=c[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;e0&&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]=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=a.styles[t];return n?"["+a.colors[n][0]+"m"+e+"["+a.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 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(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!==s.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=[],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]}(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 s,a,c;if((c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),k(r,o)||(s="["+o+"]"),a||(e.seen.indexOf(c.value)<0?(a=g(n)?l(e,c.value,null):l(e,c.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]"===_(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(),!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=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||s.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.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):T(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 _(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(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=u.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 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(M,t,e))}function M(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?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&&a(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!==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 c=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=s.length,a=c,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 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){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(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,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(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=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 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 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,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var u=n(19);u.inherits=n(14);var l={deprecate:n(64)},f=n(38),h=n(13).Buffer,p=o.Uint8Array||function(){};var d,g=n(39);function y(){}function v(e,t){a=a||n(11),e=e||{};var r=t instanceof a;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 s=S(n);s||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?c(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(11),!(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(),_(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,c=!0;n;)o[a]=n,n.isBuf||(c=!1),n=n.next,a+=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 s(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,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 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(18),n(62).setImmediate,n(10))},function(e,t,n){"use strict";e.exports=s;var r=n(11),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&&c.statusCode<300?r(new s.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}(s.a)}).call(this,n(5).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===(c=s.indexOf(r.a.RecordSeparatorCode)))throw new Error("Message is incomplete.");var a=c+1;n=String.fromCharCode.apply(null,s.slice(0,a)),i=s.byteLength>a?s.slice(a).buffer:null}else{var c,u=t;if(-1===(c=u.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");a=c+1;n=u.substring(0,a),i=u.length>a?u.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(5).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{c(r.next(e))}catch(e){i(e)}}function a(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(s,a)}c((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[c++]=t>>8&255,a[c++]=255&t;2===s&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,a[c++]=255&t);1===s&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,a[c++]=t>>8&255,a[c++]=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,c=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,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+=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-u;else{if(i===c)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,r),i-=u}return(p?-1:1)*s*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var s,a,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?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-s))<1&&(s--,c*=2),(t+=s+f>=1?h/c:h*Math.pow(2,1-f))*c>=2&&(s++,c/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*c-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,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(8))},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(9)},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(59);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(5),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(62),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(8))},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(34)).Stream=t,t.Readable=t,t.Writable=n(39),t.Duplex=n(9),t.Transform=n(40),t.PassThrough=n(66)},function(e,t,n){"use strict";e.exports=i;var r=n(40),o=n(18);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(20);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(33).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";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.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(41),o=function(){function e(e){this.document=e,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=r.AutoReconnectCircuitHandler.DialogId;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='
',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.button.addEventListener("click",function(){return window.Blazor.reconnect()})}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.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.message.textContent="Failed to reconnect to the server."},e}();t.DefaultReconnectDisplay=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]this.nextBatchId)this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed.");else try{this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),this.completeBatch(n,e)}catch(t){throw this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,t.toString()),t}},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.renderQueues=new Map,e}();t.default=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(73),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(22),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]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}},a=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};Object.defineProperty(t,"__esModule",{value:!0});var s=n(19),c=n(76),u=function(){function e(e,t){this.circuitId=e,this.components=t}return e.prototype.reconnect=function(e){return e.invoke("ConnectCircuit",this.circuitId)},e}();function l(e){if(e.nodeType===Node.COMMENT_NODE&&e.textContent){var t=/\W+M.A.C.Component:[^{]*(.*)$/.exec(e.textContent),n=t&&t[1];if(n){try{var r=JSON.parse(n),o=r.componentId,i=r.rendererId,a=r.circuitId;if(void 0!==o&&void 0!==i&&!!a)return{node:e,circuitId:a,rendererId:i,componentId:o}}catch(e){}throw new Error("Found malformed start component comment at "+e.textContent)}}}function f(e,t,n,r){for(var o=n;o>=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=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,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(10))},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(11)},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(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),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(5),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(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(10))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,s,a,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)}:(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=c,e.exports.encoder=a},function(e,t,n){(t=e.exports=n(36)).Stream=t,t.Readable=t,t.Writable=n(41),t.Duplex=n(11),t.Transform=n(42),t.PassThrough=n(67)},function(e,t,n){"use strict";e.exports=i;var r=n(42),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(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 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 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 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=[],c=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(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(a(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),s=1e6*(n-1e3*i);if(s||i>4294967295){(t=new r(10))[0]=215,t[1]=-1;var a=4*s,c=i/Math.pow(2,32),u=a+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,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)}(c)||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())}(c);else if("number"==typeof c){if((h=c)!==Math.floor(h))return s(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 s(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 s(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 s=1,a=t+7;a>=t;a--){var c=(255^e[a])+s;e[a]=255&c,s=c>>8}}(l,1,c)}}}if(!l)throw new Error("not implemented yet");return u?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{c(r.next(e))}catch(e){i(e)}}function a(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(s,a)}c((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.renderQueues=new Map,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,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 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=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}(),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(20),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{c(r.next(e))}catch(e){i(e)}}function a(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(s,a)}c((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]>=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]),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=[],a=0,c=s.parse(e);a0&&!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=f(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):d(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){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]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]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,u):"",s=u>-1?a.substring(u+1):a,c=t.monoPlatform.findMethod(e,l,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),u=Module.stackAlloc(4),l=0;l>2,r=Module.HEAPU32[n+1];if(r>v)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*h+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 b=document.createElement("a");function w(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(31),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 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(16),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=45)}([,,,,,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(25),n(9);var r=n(26),o=n(16),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(t);if(!r)throw new Error("Could not find any element matching selector '"+t+"'.");u(e,o.toLogicalElement(r,!0),n)},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),f=t.diffReader,d=0;d0&&!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=f(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):d(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;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";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]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]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]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,u):"",s=u>-1?a.substring(u+1):a,c=t.monoPlatform.findMethod(e,l,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),u=Module.stackAlloc(4),l=0;l>2,r=Module.HEAPU32[n+1];if(r>v)throw new Error("Cannot read uint64 with high order part "+r+", because the result would exceed Number.MAX_SAFE_INTEGER.");return r*h+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 b=document.createElement("a");function w(e){return e+12}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(33),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 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(9),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/package.json b/src/Components/Web.JS/package.json index dcd3fbac64..ea59361494 100644 --- a/src/Components/Web.JS/package.json +++ b/src/Components/Web.JS/package.json @@ -13,22 +13,21 @@ "devDependencies": { "@aspnet/signalr": "link:../../SignalR/clients/ts/signalr", "@aspnet/signalr-protocol-msgpack": "link:../../SignalR/clients/ts/signalr-protocol-msgpack", - "@dotnet/jsinterop": "3.0.0-preview6.19280.1", + "@dotnet/jsinterop": "https://dotnet.myget.org/F/aspnetcore-dev/npm/@dotnet/jsinterop/-/@dotnet/jsinterop-3.0.0-preview8.19367.2.tgz", "@types/emscripten": "0.0.31", "@types/jest": "^24.0.6", "@types/jsdom": "11.0.6", "@typescript-eslint/eslint-plugin": "^1.5.0", "@typescript-eslint/parser": "^1.5.0", "eslint": "^5.16.0", - "jest": "^24.1.0", + "jest": "^24.8.0", "ts-jest": "^24.0.0", "ts-loader": "^4.4.1", - "typescript": "^3.4.0", - "webpack": "^4.12.0", - "webpack-cli": "^3.0.8" + "typescript": "^3.5.3", + "webpack": "^4.36.1", + "webpack-cli": "^3.3.6" }, "resolutions": { - "**/js-yaml": "^3.13.1", - "jest/**/handlebars": "^4.1.2" + "**/set-value": "^2.0.1" } } diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index 7ccc9cb13b..df96f1031f 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -3,101 +3,56 @@ import './GlobalExports'; import * as signalR from '@aspnet/signalr'; import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack'; import { shouldAutoStart } from './BootCommon'; -import { CircuitHandler } from './Platform/Circuits/CircuitHandler'; -import { AutoReconnectCircuitHandler } from './Platform/Circuits/AutoReconnectCircuitHandler'; -import RenderQueue from './Platform/Circuits/RenderQueue'; +import { RenderQueue } from './Platform/Circuits/RenderQueue'; import { ConsoleLogger } from './Platform/Logging/Loggers'; -import { LogLevel, ILogger } from './Platform/Logging/ILogger'; -import { discoverPrerenderedCircuits, startCircuit } from './Platform/Circuits/CircuitManager'; - - -type SignalRBuilder = (builder: signalR.HubConnectionBuilder) => void; -interface BlazorOptions { - configureSignalR: SignalRBuilder; - logLevel: LogLevel; -} +import { LogLevel, Logger } from './Platform/Logging/Logger'; +import { startCircuit } from './Platform/Circuits/CircuitManager'; +import { setEventDispatcher } from './Rendering/RendererEventDispatcher'; +import { resolveOptions, BlazorOptions } from './Platform/Circuits/BlazorOptions'; +import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler'; let renderingFailed = false; let started = false; async function boot(userOptions?: Partial): Promise { - if (started) { throw new Error('Blazor has already started.'); } started = true; - const defaultOptions: BlazorOptions = { - configureSignalR: (_) => { }, - logLevel: LogLevel.Warning, - }; - - const options: BlazorOptions = { ...defaultOptions, ...userOptions }; - - // For development. - // Simply put a break point here and modify the log level during - // development to get traces. - // In the future we will allow for users to configure this. + // Establish options to be used + const options = resolveOptions(userOptions); const logger = new ConsoleLogger(options.logLevel); - + window['Blazor'].defaultReconnectionHandler = new DefaultReconnectionHandler(logger); + options.reconnectionHandler = options.reconnectionHandler || window['Blazor'].defaultReconnectionHandler; logger.log(LogLevel.Information, 'Starting up blazor server-side application.'); - const circuitHandlers: CircuitHandler[] = [new AutoReconnectCircuitHandler(logger)]; - window['Blazor'].circuitHandlers = circuitHandlers; - - // pass options.configureSignalR to configure the signalR.HubConnectionBuilder - const initialConnection = await initializeConnection(options, circuitHandlers, logger); - - const circuits = discoverPrerenderedCircuits(document); - for (let i = 0; i < circuits.length; i++) { - const circuit = circuits[i]; - for (let j = 0; j < circuit.components.length; j++) { - const component = circuit.components[j]; - component.initialize(); - } - } - + const initialConnection = await initializeConnection(options, logger); const circuit = await startCircuit(initialConnection); - if (!circuit) { - logger.log(LogLevel.Information, 'No preregistered components to render.'); - } - const reconnect = async (existingConnection?: signalR.HubConnection): Promise => { if (renderingFailed) { // We can't reconnect after a failure, so exit early. return false; } - const reconnection = existingConnection || await initializeConnection(options, circuitHandlers, logger); - const results = await Promise.all(circuits.map(circuit => circuit.reconnect(reconnection))); - if (reconnectionFailed(results)) { + const reconnection = existingConnection || await initializeConnection(options, logger); + if (!(await circuit.reconnect(reconnection))) { + logger.log(LogLevel.Information, 'Reconnection attempt failed.'); return false; } - circuitHandlers.forEach(h => h.onConnectionUp && h.onConnectionUp()); + options.reconnectionHandler!.onConnectionUp(); + return true; }; window['Blazor'].reconnect = reconnect; - const reconnectTask = reconnect(initialConnection); - - if (circuit) { - circuits.push(circuit); - } - - await reconnectTask; - logger.log(LogLevel.Information, 'Blazor server-side application started.'); - - function reconnectionFailed(results: boolean[]): boolean { - return !results.reduce((current, next) => current && next, true); - } } -async function initializeConnection(options: Required, circuitHandlers: CircuitHandler[], logger: ILogger): Promise { - +async function initializeConnection(options: BlazorOptions, logger: Logger): Promise { const hubProtocol = new MessagePackHubProtocol(); (hubProtocol as unknown as { name: string }).name = 'blazorpack'; @@ -109,7 +64,17 @@ async function initializeConnection(options: Required, circuitHan const connection = connectionBuilder.build(); + setEventDispatcher((descriptor, args) => { + return connection.send('DispatchBrowserEvent', JSON.stringify(descriptor), JSON.stringify(args)); + }); + + // Configure navigation via SignalR + window['Blazor']._internal.navigationManager.listenForNavigationEvents((uri: string, intercepted: boolean): Promise => { + return connection.send('OnLocationChanged', uri, intercepted); + }); + connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet); + connection.on('JS.EndInvokeDotNet', (args: string) => DotNet.jsCallDispatcher.endInvokeDotNetFromJS(...(JSON.parse(args) as [string, boolean, unknown]))); connection.on('JS.RenderBatch', (browserRendererId: number, batchId: number, batchData: Uint8Array) => { logger.log(LogLevel.Debug, `Received render batch for ${browserRendererId} with id ${batchId} and ${batchData.byteLength} bytes.`); @@ -118,8 +83,11 @@ async function initializeConnection(options: Required, circuitHan queue.processBatch(batchId, batchData, connection); }); - connection.onclose(error => !renderingFailed && circuitHandlers.forEach(h => h.onConnectionDown && h.onConnectionDown(error))); - connection.on('JS.Error', error => unhandledError(connection, error, logger)); + connection.onclose(error => !renderingFailed && options.reconnectionHandler!.onConnectionDown(options.reconnectionOptions, error)); + connection.on('JS.Error', error => { + renderingFailed = true; + unhandledError(connection, error, logger); + }); window['Blazor']._internal.forceCloseConnection = () => connection.stop(); @@ -130,27 +98,30 @@ async function initializeConnection(options: Required, circuitHan } DotNet.attachDispatcher({ - beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson) => { + beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson): void => { connection.send('BeginInvokeDotNetFromJS', callId ? callId.toString() : null, assemblyName, methodIdentifier, dotNetObjectId || 0, argsJson); }, + endInvokeJSFromDotNet: (asyncHandle, succeeded, argsJson): void => { + connection.send('EndInvokeJSFromDotNet', asyncHandle, succeeded, argsJson); + }, }); return connection; } -function unhandledError(connection: signalR.HubConnection, err: Error, logger: ILogger): void { +function unhandledError(connection: signalR.HubConnection, err: Error, logger: Logger): void { logger.log(LogLevel.Error, err); // Disconnect on errors. // // Trying to call methods on the connection after its been closed will throw. if (connection) { - renderingFailed = true; connection.stop(); } } window['Blazor'].start = boot; + if (shouldAutoStart()) { boot(); } diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index fe17439bfd..ee990a10c2 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -7,16 +7,19 @@ import { renderBatch } from './Rendering/Renderer'; import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch'; import { Pointer } from './Platform/Platform'; import { fetchBootConfigAsync, loadEmbeddedResourcesAsync, shouldAutoStart } from './BootCommon'; +import { setEventDispatcher } from './Rendering/RendererEventDispatcher'; let started = false; -async function boot(options?: any) { +async function boot(options?: any): Promise { if (started) { throw new Error('Blazor has already started.'); } started = true; + setEventDispatcher((eventDescriptor, eventArgs) => DotNet.invokeMethodAsync('Microsoft.AspNetCore.Components.Web', 'DispatchEvent', eventDescriptor, JSON.stringify(eventArgs))); + // Configure environment for execution under Mono WebAssembly with shared-memory rendering const platform = Environment.setPlatform(monoPlatform); window['Blazor'].platform = platform; @@ -24,6 +27,16 @@ async function boot(options?: any) { renderBatch(browserRendererId, new SharedMemoryRenderBatch(batchAddress)); }; + // Configure navigation via JS Interop + window['Blazor']._internal.navigationManager.listenForNavigationEvents(async (uri: string, intercepted: boolean): Promise => { + await DotNet.invokeMethodAsync( + 'Microsoft.AspNetCore.Blazor', + 'NotifyLocationChanged', + uri, + intercepted + ); + }); + // Fetch the boot JSON file const bootConfig = await fetchBootConfigAsync(); const embeddedResourcesPromise = loadEmbeddedResourcesAsync(bootConfig); @@ -54,4 +67,4 @@ async function boot(options?: any) { window['Blazor'].start = boot; if (shouldAutoStart()) { boot(); -} \ No newline at end of file +} diff --git a/src/Components/Web.JS/src/BootCommon.ts b/src/Components/Web.JS/src/BootCommon.ts index 959cac3e16..d9995ea911 100644 --- a/src/Components/Web.JS/src/BootCommon.ts +++ b/src/Components/Web.JS/src/BootCommon.ts @@ -40,7 +40,7 @@ interface BootJsonData { // Tells you if the script was added without export function shouldAutoStart() { - return document && + return !!(document && document.currentScript && - document.currentScript.getAttribute('autostart') !== 'false'; -} \ No newline at end of file + document.currentScript.getAttribute('autostart') !== 'false'); +} diff --git a/src/Components/Web.JS/src/GlobalExports.ts b/src/Components/Web.JS/src/GlobalExports.ts index 4ffb9f2ae6..005432545a 100644 --- a/src/Components/Web.JS/src/GlobalExports.ts +++ b/src/Components/Web.JS/src/GlobalExports.ts @@ -1,4 +1,4 @@ -import { navigateTo, internalFunctions as uriHelperInternalFunctions } from './Services/UriHelper'; +import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager'; import { internalFunctions as httpInternalFunctions } from './Services/Http'; import { attachRootComponentToElement } from './Rendering/Renderer'; @@ -9,6 +9,6 @@ window['Blazor'] = { _internal: { attachRootComponentToElement, http: httpInternalFunctions, - uriHelper: uriHelperInternalFunctions, + navigationManager: navigationManagerInternalFunctions, }, }; diff --git a/src/Components/Web.JS/src/Platform/Circuits/AutoReconnectCircuitHandler.ts b/src/Components/Web.JS/src/Platform/Circuits/AutoReconnectCircuitHandler.ts deleted file mode 100644 index 090a164c07..0000000000 --- a/src/Components/Web.JS/src/Platform/Circuits/AutoReconnectCircuitHandler.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { CircuitHandler } from './CircuitHandler'; -import { UserSpecifiedDisplay } from './UserSpecifiedDisplay'; -import { DefaultReconnectDisplay } from './DefaultReconnectDisplay'; -import { ReconnectDisplay } from './ReconnectDisplay'; -import { ILogger, LogLevel } from '../Logging/ILogger'; -export class AutoReconnectCircuitHandler implements CircuitHandler { - public static readonly MaxRetries = 5; - - public static readonly RetryInterval = 3000; - - public static readonly DialogId = 'components-reconnect-modal'; - - public reconnectDisplay: ReconnectDisplay; - - public logger: ILogger; - - public constructor(logger: ILogger) { - this.logger = logger; - this.reconnectDisplay = new DefaultReconnectDisplay(document); - document.addEventListener('DOMContentLoaded', () => { - const modal = document.getElementById(AutoReconnectCircuitHandler.DialogId); - if (modal) { - this.reconnectDisplay = new UserSpecifiedDisplay(modal); - } - }); - } - - public onConnectionUp(): void { - this.reconnectDisplay.hide(); - } - - public delay(): Promise { - return new Promise((resolve) => setTimeout(resolve, AutoReconnectCircuitHandler.RetryInterval)); - } - - public async onConnectionDown(): Promise { - this.reconnectDisplay.show(); - - for (let i = 0; i < AutoReconnectCircuitHandler.MaxRetries; i++) { - await this.delay(); - try { - const result = await window['Blazor'].reconnect(); - if (!result) { - // If the server responded and refused to reconnect, stop auto-retrying. - break; - } - return; - } catch (err) { - this.logger.log(LogLevel.Error, err); - } - } - - this.reconnectDisplay.failed(); - } -} diff --git a/src/Components/Web.JS/src/Platform/Circuits/BlazorOptions.ts b/src/Components/Web.JS/src/Platform/Circuits/BlazorOptions.ts new file mode 100644 index 0000000000..10d0c9a357 --- /dev/null +++ b/src/Components/Web.JS/src/Platform/Circuits/BlazorOptions.ts @@ -0,0 +1,40 @@ +import { LogLevel } from '../Logging/Logger'; + +export interface BlazorOptions { + configureSignalR: (builder: signalR.HubConnectionBuilder) => void; + logLevel: LogLevel; + reconnectionOptions: ReconnectionOptions; + reconnectionHandler?: ReconnectionHandler; +} + +export function resolveOptions(userOptions?: Partial): BlazorOptions { + const result = { ...defaultOptions, ...userOptions }; + + // The spread operator can't be used for a deep merge, so do the same for subproperties + if (userOptions && userOptions.reconnectionOptions) { + result.reconnectionOptions = { ...defaultOptions.reconnectionOptions, ...userOptions.reconnectionOptions }; + } + + return result; +} + +export interface ReconnectionOptions { + maxRetries: number; + retryIntervalMilliseconds: number; + dialogId: string; +} + +export interface ReconnectionHandler { + onConnectionDown(options: ReconnectionOptions, error?: Error): void; + onConnectionUp(): void; +} + +const defaultOptions: BlazorOptions = { + configureSignalR: (_) => { }, + logLevel: LogLevel.Warning, + reconnectionOptions: { + maxRetries: 5, + retryIntervalMilliseconds: 3000, + dialogId: 'components-reconnect-modal', + }, +}; diff --git a/src/Components/Web.JS/src/Platform/Circuits/CircuitHandler.ts b/src/Components/Web.JS/src/Platform/Circuits/CircuitHandler.ts deleted file mode 100644 index ab52e0840d..0000000000 --- a/src/Components/Web.JS/src/Platform/Circuits/CircuitHandler.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface CircuitHandler { - /** Invoked when a server connection is established or re-established after a connection failure. - */ - onConnectionUp?(): void; - - /** Invoked when a server connection is dropped. - * @param {Error} error Optionally argument containing the error that caused the connection to close (if any). - */ - onConnectionDown?(error?: Error): void; -} diff --git a/src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts b/src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts index 44e351a8f1..c99ec42f08 100644 --- a/src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts +++ b/src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts @@ -1,14 +1,10 @@ -import { internalFunctions as uriHelperFunctions } from '../../Services/UriHelper'; -import { ComponentDescriptor, MarkupRegistrationTags, StartComponentComment, EndComponentComment } from './ComponentDescriptor'; +import { internalFunctions as navigationManagerFunctions } from '../../Services/NavigationManager'; export class CircuitDescriptor { public circuitId: string; - public components: ComponentDescriptor[]; - - public constructor(circuitId: string, components: ComponentDescriptor[]) { + public constructor(circuitId: string) { this.circuitId = circuitId; - this.components = components; } public reconnect(reconnection: signalR.HubConnection): Promise { @@ -16,115 +12,11 @@ export class CircuitDescriptor { } } - -export function discoverPrerenderedCircuits(document: Document): CircuitDescriptor[] { - const commentPairs = resolveCommentPairs(document); - const discoveredCircuits = new Map(); - for (let i = 0; i < commentPairs.length; i++) { - const pair = commentPairs[i]; - // We replace '--' on the server with '..' when we prerender due to the fact that this - // is not allowed in HTML comments and doesn't get encoded by default. - const circuitId = pair.start.circuitId.replace('..', '--'); - let circuit = discoveredCircuits.get(circuitId); - if (!circuit) { - circuit = []; - discoveredCircuits.set(circuitId, circuit); - } - const entry = new ComponentDescriptor(pair.start.componentId, circuitId, pair.start.rendererId, pair); - circuit.push(entry); - } - const circuits: CircuitDescriptor[] = []; - for (const [key, values] of discoveredCircuits) { - circuits.push(new CircuitDescriptor(key, values)); - } - return circuits; -} - -export async function startCircuit(connection: signalR.HubConnection): Promise { - const result = await connection.invoke('StartCircuit', uriHelperFunctions.getLocationHref(), uriHelperFunctions.getBaseURI()); +export async function startCircuit(connection: signalR.HubConnection): Promise { + const result = await connection.invoke('StartCircuit', navigationManagerFunctions.getBaseURI(), navigationManagerFunctions.getLocationHref()); if (result) { - return new CircuitDescriptor(result, []); + return new CircuitDescriptor(result); } else { - return undefined; + throw new Error('Circuit failed to start'); } } - -function resolveCommentPairs(node: Node): MarkupRegistrationTags[] { - if (!node.hasChildNodes()) { - return []; - } - const result: MarkupRegistrationTags[] = []; - const children = node.childNodes; - let i = 0; - const childrenLength = children.length; - while (i < childrenLength) { - const currentChildNode = children[i]; - const startComponent = getComponentStartComment(currentChildNode); - if (!startComponent) { - i++; - const childResults = resolveCommentPairs(currentChildNode); - for (let j = 0; j < childResults.length; j++) { - const childResult = childResults[j]; - result.push(childResult); - } - continue; - } - const endComponent = getComponentEndComment(startComponent, children, i + 1, childrenLength); - result.push({ start: startComponent, end: endComponent }); - i = endComponent.index + 1; - } - return result; -} -function getComponentStartComment(node: Node): StartComponentComment | undefined { - if (node.nodeType !== Node.COMMENT_NODE) { - return; - } - if (node.textContent) { - const componentStartComment = /\W+M.A.C.Component:[^{]*(.*)$/; - const definition = componentStartComment.exec(node.textContent); - const json = definition && definition[1]; - if (json) { - try { - const { componentId, rendererId, circuitId } = JSON.parse(json); - const allComponents = componentId !== undefined && rendererId !== undefined && !!circuitId; - if (allComponents) { - return { - node: node as Comment, - circuitId, - rendererId: rendererId, - componentId: componentId, - }; - } - } catch (error) { - } - throw new Error(`Found malformed start component comment at ${node.textContent}`); - } - } -} -function getComponentEndComment(component: StartComponentComment, children: NodeList, index: number, end: number): EndComponentComment { - for (let i = index; i < end; i++) { - const node = children[i]; - if (node.nodeType !== Node.COMMENT_NODE) { - continue; - } - if (!node.textContent) { - continue; - } - const componentEndComment = /\W+M.A.C.Component:\W+(\d+)\W+$/; - const definition = componentEndComment.exec(node.textContent); - const json = definition && definition[1]; - if (!json) { - continue; - } - try { - // The value is expected to be a JSON encoded number - const componentId = JSON.parse(json); - if (componentId === component.componentId) { - return { componentId, node: node as Comment, index: i }; - } - } catch (error) { - } - throw new Error(`Found malformed end component comment at ${node.textContent}`); - } - throw new Error(`End component comment not found for ${component.node}`); -} diff --git a/src/Components/Web.JS/src/Platform/Circuits/ComponentDescriptor.ts b/src/Components/Web.JS/src/Platform/Circuits/ComponentDescriptor.ts deleted file mode 100644 index 5f387cc2dc..0000000000 --- a/src/Components/Web.JS/src/Platform/Circuits/ComponentDescriptor.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { attachRootComponentToLogicalElement } from '../../Rendering/Renderer'; -import { toLogicalRootCommentElement } from '../../Rendering/LogicalElements'; - -export interface EndComponentComment { - componentId: number; - node: Comment; - index: number; -} - -export interface StartComponentComment { - node: Comment; - rendererId: number; - componentId: number; - circuitId: string; -} - -// Represent pairs of start end comments indicating a component that was registered -// in markup (such as a prerendered component) -export interface MarkupRegistrationTags { - start: StartComponentComment; - end: EndComponentComment; -} - -export class ComponentDescriptor { - public registrationTags: MarkupRegistrationTags; - - public componentId: number; - - public circuitId: string; - - public rendererId: number; - - public constructor(componentId: number, circuitId: string, rendererId: number, descriptor: MarkupRegistrationTags) { - this.componentId = componentId; - this.circuitId = circuitId; - this.rendererId = rendererId; - this.registrationTags = descriptor; - } - - public initialize(): void { - const startEndPair = { start: this.registrationTags.start.node, end: this.registrationTags.end.node }; - - const logicalElement = toLogicalRootCommentElement(startEndPair.start, startEndPair.end); - attachRootComponentToLogicalElement(this.rendererId, logicalElement, this.componentId); - } -} diff --git a/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts b/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts index 94643f80e6..2356e133ef 100644 --- a/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts +++ b/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts @@ -1,5 +1,5 @@ import { ReconnectDisplay } from './ReconnectDisplay'; -import { AutoReconnectCircuitHandler } from './AutoReconnectCircuitHandler'; + export class DefaultReconnectDisplay implements ReconnectDisplay { modal: HTMLDivElement; @@ -9,9 +9,11 @@ export class DefaultReconnectDisplay implements ReconnectDisplay { addedToDom: boolean = false; - constructor(private document: Document) { + reloadParagraph: HTMLParagraphElement; + + constructor(dialogId: string, private document: Document) { this.modal = this.document.createElement('div'); - this.modal.id = AutoReconnectCircuitHandler.DialogId; + this.modal.id = dialogId; const modalStyles = [ 'position: fixed', @@ -29,11 +31,13 @@ export class DefaultReconnectDisplay implements ReconnectDisplay { ]; this.modal.style.cssText = modalStyles.join(';'); - this.modal.innerHTML = '
'; + this.modal.innerHTML = '

Alternatively, reload

'; this.message = this.modal.querySelector('h5')!; this.button = this.modal.querySelector('button')!; + this.reloadParagraph = this.modal.querySelector('p')!; this.button.addEventListener('click', () => window['Blazor'].reconnect()); + this.reloadParagraph.querySelector('a')!.addEventListener('click', () => location.reload()); } show(): void { @@ -43,6 +47,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay { } this.modal.style.display = 'block'; this.button.style.display = 'none'; + this.reloadParagraph.style.display = 'none'; this.message.textContent = 'Attempting to reconnect to the server...'; } @@ -52,6 +57,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay { failed(): void { this.button.style.display = 'block'; + this.reloadParagraph.style.display = 'block'; this.message.textContent = 'Failed to reconnect to the server.'; } } diff --git a/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectionHandler.ts b/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectionHandler.ts new file mode 100644 index 0000000000..22b196ef54 --- /dev/null +++ b/src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectionHandler.ts @@ -0,0 +1,85 @@ +import { ReconnectionHandler, ReconnectionOptions } from './BlazorOptions'; +import { ReconnectDisplay } from './ReconnectDisplay'; +import { DefaultReconnectDisplay } from './DefaultReconnectDisplay'; +import { UserSpecifiedDisplay } from './UserSpecifiedDisplay'; +import { Logger, LogLevel } from '../Logging/Logger'; + +export class DefaultReconnectionHandler implements ReconnectionHandler { + private readonly _logger: Logger; + private readonly _reconnectCallback: () => Promise; + private _currentReconnectionProcess: ReconnectionProcess | null = null; + private _reconnectionDisplay?: ReconnectDisplay; + + constructor(logger: Logger, overrideDisplay?: ReconnectDisplay, reconnectCallback?: () => Promise) { + this._logger = logger; + this._reconnectionDisplay = overrideDisplay; + this._reconnectCallback = reconnectCallback || (() => window['Blazor'].reconnect()); + } + + onConnectionDown (options: ReconnectionOptions, error?: Error) { + if (!this._reconnectionDisplay) { + const modal = document.getElementById(options.dialogId); + this._reconnectionDisplay = modal + ? new UserSpecifiedDisplay(modal) + : new DefaultReconnectDisplay(options.dialogId, document); + } + + if (!this._currentReconnectionProcess) { + this._currentReconnectionProcess = new ReconnectionProcess(options, this._logger, this._reconnectCallback, this._reconnectionDisplay!); + } + } + + onConnectionUp() { + if (this._currentReconnectionProcess) { + this._currentReconnectionProcess.dispose(); + this._currentReconnectionProcess = null; + } + } +}; + +class ReconnectionProcess { + readonly reconnectDisplay: ReconnectDisplay; + isDisposed = false; + + constructor(options: ReconnectionOptions, private logger: Logger, private reconnectCallback: () => Promise, display: ReconnectDisplay) { + this.reconnectDisplay = display; + this.reconnectDisplay.show(); + this.attemptPeriodicReconnection(options); + } + + public dispose() { + this.isDisposed = true; + this.reconnectDisplay.hide(); + } + + async attemptPeriodicReconnection(options: ReconnectionOptions) { + for (let i = 0; i < options.maxRetries; i++) { + await this.delay(options.retryIntervalMilliseconds); + if (this.isDisposed) { + break; + } + + try { + // reconnectCallback will asynchronously return: + // - true to mean success + // - false to mean we reached the server, but it rejected the connection (e.g., unknown circuit ID) + // - exception to mean we didn't reach the server (this can be sync or async) + const result = await this.reconnectCallback(); + if (!result) { + // If the server responded and refused to reconnect, stop auto-retrying. + break; + } + return; + } catch (err) { + // We got an exception so will try again momentarily + this.logger.log(LogLevel.Error, err); + } + } + + this.reconnectDisplay.failed(); + } + + delay(durationMilliseconds: number): Promise { + return new Promise(resolve => setTimeout(resolve, durationMilliseconds)); + } +} diff --git a/src/Components/Web.JS/src/Platform/Circuits/RenderQueue.ts b/src/Components/Web.JS/src/Platform/Circuits/RenderQueue.ts index 1039ce3b22..78860d111c 100644 --- a/src/Components/Web.JS/src/Platform/Circuits/RenderQueue.ts +++ b/src/Components/Web.JS/src/Platform/Circuits/RenderQueue.ts @@ -1,23 +1,25 @@ import { renderBatch } from '../../Rendering/Renderer'; import { OutOfProcessRenderBatch } from '../../Rendering/RenderBatch/OutOfProcessRenderBatch'; -import { ILogger, LogLevel } from '../Logging/ILogger'; +import { Logger, LogLevel } from '../Logging/Logger'; import { HubConnection } from '@aspnet/signalr'; -export default class RenderQueue { +export class RenderQueue { private static renderQueues = new Map(); private nextBatchId = 2; + private fatalError?: string; + public browserRendererId: number; - public logger: ILogger; + public logger: Logger; - public constructor(browserRendererId: number, logger: ILogger) { + public constructor(browserRendererId: number, logger: Logger) { this.browserRendererId = browserRendererId; this.logger = logger; } - public static getOrCreateQueue(browserRendererId: number, logger: ILogger): RenderQueue { + public static getOrCreateQueue(browserRendererId: number, logger: Logger): RenderQueue { const queue = this.renderQueues.get(browserRendererId); if (queue) { return queue; @@ -28,13 +30,23 @@ export default class RenderQueue { return newQueue; } - public processBatch(receivedBatchId: number, batchData: Uint8Array, connection: HubConnection): void { + public async processBatch(receivedBatchId: number, batchData: Uint8Array, connection: HubConnection): Promise { if (receivedBatchId < this.nextBatchId) { + // SignalR delivers messages in order, but it does not guarantee that the message gets delivered. + // For that reason, if the server re-sends a batch (for example during a reconnection because it didn't get an ack) + // we simply acknowledge it to get back in sync with the server. + await this.completeBatch(connection, receivedBatchId); this.logger.log(LogLevel.Debug, `Batch ${receivedBatchId} already processed. Waiting for batch ${this.nextBatchId}.`); return; } if (receivedBatchId > this.nextBatchId) { + if (this.fatalError) { + this.logger.log(LogLevel.Debug, `Received a new batch ${receivedBatchId} but errored out on a previous batch ${this.nextBatchId - 1}`); + await connection.send('OnRenderCompleted', this.nextBatchId - 1, this.fatalError.toString()); + return; + } + this.logger.log(LogLevel.Debug, `Waiting for batch ${this.nextBatchId}. Batch ${receivedBatchId} not processed.`); return; } @@ -43,8 +55,9 @@ export default class RenderQueue { this.nextBatchId++; this.logger.log(LogLevel.Debug, `Applying batch ${receivedBatchId}.`); renderBatch(this.browserRendererId, new OutOfProcessRenderBatch(batchData)); - this.completeBatch(connection, receivedBatchId); + await this.completeBatch(connection, receivedBatchId); } catch (error) { + this.fatalError = error.toString(); this.logger.log(LogLevel.Error, `There was an error applying batch ${receivedBatchId}.`); // If there's a rendering exception, notify server *and* throw on client diff --git a/src/Components/Web.JS/src/Platform/Logging/ILogger.ts b/src/Components/Web.JS/src/Platform/Logging/Logger.ts similarity index 94% rename from src/Components/Web.JS/src/Platform/Logging/ILogger.ts rename to src/Components/Web.JS/src/Platform/Logging/Logger.ts index 049dcd9369..13f6a7c8a6 100644 --- a/src/Components/Web.JS/src/Platform/Logging/ILogger.ts +++ b/src/Components/Web.JS/src/Platform/Logging/Logger.ts @@ -24,7 +24,7 @@ export enum LogLevel { } /** An abstraction that provides a sink for diagnostic messages. */ -export interface ILogger { // eslint-disable-line @typescript-eslint/interface-name-prefix +export interface Logger { // eslint-disable-line @typescript-eslint/interface-name-prefix /** Called by the framework to emit a diagnostic message. * * @param {LogLevel} logLevel The severity level of the message. diff --git a/src/Components/Web.JS/src/Platform/Logging/Loggers.ts b/src/Components/Web.JS/src/Platform/Logging/Loggers.ts index 547e78a2e4..ac2a938da6 100644 --- a/src/Components/Web.JS/src/Platform/Logging/Loggers.ts +++ b/src/Components/Web.JS/src/Platform/Logging/Loggers.ts @@ -1,9 +1,9 @@ /* eslint-disable no-console */ -import { ILogger, LogLevel } from './ILogger'; +import { Logger, LogLevel } from './Logger'; -export class NullLogger implements ILogger { - public static instance: ILogger = new NullLogger(); +export class NullLogger implements Logger { + public static instance: Logger = new NullLogger(); private constructor() { } @@ -11,7 +11,7 @@ export class NullLogger implements ILogger { } } -export class ConsoleLogger implements ILogger { +export class ConsoleLogger implements Logger { private readonly minimumLogLevel: LogLevel; public constructor(minimumLogLevel: LogLevel) { diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 78930a7d52..4dd81da9a5 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -281,7 +281,7 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: () }); module.postRun.push(() => { - MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE","true"); + MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE", "true"); const load_runtime = Module.cwrap('mono_wasm_load_runtime', null, ['string', 'number']); load_runtime(appBinDirName, hasDebuggingEnabled() ? 1 : 0); MONO.mono_wasm_runtime_is_ready = true; @@ -298,7 +298,7 @@ function toAbsoluteUrl(possiblyRelativeUrl: string) { return anchorTagForAbsoluteUrlConversions.href; } -function asyncLoad(url) { +function asyncLoad(url: string) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url, /* async: */ true); @@ -320,26 +320,36 @@ function getArrayDataPointer(array: System_Array): number { return array + 12; // First byte from here is length, then following bytes are entries } -function attachInteropInvoker() { +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'); DotNet.attachDispatcher({ - beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson) => { + beginInvokeDotNetFromJS: (callId: number, assemblyName: string | null, methodIdentifier: string, dotNetObjectId: any | null, argsJson: string): void => { + if (!dotNetObjectId && !assemblyName) { + throw new Error('Either assemblyName or dotNetObjectId must have a non null value.'); + } // As a current limitation, we can only pass 4 args. Fortunately we only need one of // 'assemblyName' or 'dotNetObjectId', so overload them in a single slot - const assemblyNameOrDotNetObjectId = dotNetObjectId + const assemblyNameOrDotNetObjectId: string = dotNetObjectId ? dotNetObjectId.toString() : assemblyName; monoPlatform.callMethod(dotNetDispatcherBeginInvokeMethodHandle, null, [ callId ? monoPlatform.toDotNetString(callId.toString()) : null, - monoPlatform.toDotNetString(assemblyNameOrDotNetObjectId!), + monoPlatform.toDotNetString(assemblyNameOrDotNetObjectId), monoPlatform.toDotNetString(methodIdentifier), monoPlatform.toDotNetString(argsJson), ]); }, - + endInvokeJSFromDotNet: (asyncHandle, succeeded, serializedArgs): void => { + monoPlatform.callMethod( + dotNetDispatcherEndInvokeJSMethodHandle, + null, + [monoPlatform.toDotNetString(serializedArgs)] + ); + }, invokeDotNetFromJS: (assemblyName, methodIdentifier, dotNetObjectId, argsJson) => { const resultJsonStringPtr = monoPlatform.callMethod(dotNetDispatcherInvokeMethodHandle, null, [ assemblyName ? monoPlatform.toDotNetString(assemblyName) : null, diff --git a/src/Components/Web.JS/src/Rendering/BrowserRenderer.ts b/src/Components/Web.JS/src/Rendering/BrowserRenderer.ts index 62b9e1de21..7e763d6760 100644 --- a/src/Components/Web.JS/src/Rendering/BrowserRenderer.ts +++ b/src/Components/Web.JS/src/Rendering/BrowserRenderer.ts @@ -1,9 +1,10 @@ import { RenderBatch, ArrayBuilderSegment, RenderTreeEdit, RenderTreeFrame, EditType, FrameType, ArrayValues } from './RenderBatch/RenderBatch'; import { EventDelegator } from './EventDelegator'; -import { EventForDotNet, UIEventArgs } from './EventForDotNet'; +import { EventForDotNet, UIEventArgs, EventArgsType } from './EventForDotNet'; import { LogicalElement, PermutationListEntry, toLogicalElement, insertLogicalChild, removeLogicalChild, getLogicalParent, getLogicalChild, createAndInsertLogicalContainer, isSvgElement, getLogicalChildrenArray, getLogicalSiblingEnd, permuteLogicalChildren, getClosestDomElement } from './LogicalElements'; import { applyCaptureIdToElement } from './ElementReferenceCapture'; import { EventFieldInfo } from './EventFieldInfo'; +import { dispatchEvent } from './RendererEventDispatcher'; const selectValuePropname = '_blazorSelectValue'; const sharedTemplateElemForParsing = document.createElement('template'); const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g'); @@ -398,6 +399,13 @@ export interface ComponentDescriptor { end: Node; } +export interface EventDescriptor { + browserRendererId: number; + eventHandlerId: number; + eventArgsType: EventArgsType; + eventFieldInfo: EventFieldInfo | null; +} + function parseMarkup(markup: string, isSvg: boolean) { if (isSvg) { sharedSvgElemForParsing.innerHTML = markup || ' '; @@ -423,7 +431,13 @@ function countDescendantFrames(batch: RenderBatch, frame: RenderTreeFrame): numb } } -function raiseEvent(event: Event, browserRendererId: number, eventHandlerId: number, eventArgs: EventForDotNet, eventFieldInfo: EventFieldInfo | null) { +function raiseEvent( + event: Event, + browserRendererId: number, + eventHandlerId: number, + eventArgs: EventForDotNet, + eventFieldInfo: EventFieldInfo | null +): void { if (preventDefaultEvents[event.type]) { event.preventDefault(); } @@ -435,12 +449,7 @@ function raiseEvent(event: Event, browserRendererId: number, eventHandlerId: num eventFieldInfo: eventFieldInfo, }; - return DotNet.invokeMethodAsync( - 'Microsoft.AspNetCore.Components.Web', - 'DispatchEvent', - eventDescriptor, - JSON.stringify(eventArgs.data) - ); + dispatchEvent(eventDescriptor, eventArgs.data); } function clearElement(element: Element) { @@ -452,7 +461,7 @@ function clearElement(element: Element) { function clearBetween(start: Node, end: Node): void { const logicalParent = getLogicalParent(start as unknown as LogicalElement); - if (!logicalParent){ + if (!logicalParent) { throw new Error("Can't clear between nodes. The start node does not have a logical parent."); } const children = getLogicalChildrenArray(logicalParent); diff --git a/src/Components/Web.JS/src/Rendering/EventForDotNet.ts b/src/Components/Web.JS/src/Rendering/EventForDotNet.ts index 18120f11e9..63dea2cc1f 100644 --- a/src/Components/Web.JS/src/Rendering/EventForDotNet.ts +++ b/src/Components/Web.JS/src/Rendering/EventForDotNet.ts @@ -210,7 +210,7 @@ function isCheckbox(element: Element | null) { // The following interfaces must be kept in sync with the UIEventArgs C# classes -type EventArgsType = 'change' | 'clipboard' | 'drag' | 'error' | 'focus' | 'keyboard' | 'mouse' | 'pointer' | 'progress' | 'touch' | 'unknown' | 'wheel'; +export type EventArgsType = 'change' | 'clipboard' | 'drag' | 'error' | 'focus' | 'keyboard' | 'mouse' | 'pointer' | 'progress' | 'touch' | 'unknown' | 'wheel'; export interface UIEventArgs { type: string; diff --git a/src/Components/Web.JS/src/Rendering/Renderer.ts b/src/Components/Web.JS/src/Rendering/Renderer.ts index 569df50d0e..88a21d16a6 100644 --- a/src/Components/Web.JS/src/Rendering/Renderer.ts +++ b/src/Components/Web.JS/src/Rendering/Renderer.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { System_Object, System_String, System_Array, MethodHandle, Pointer } from '../Platform/Platform'; -import { platform } from '../Environment'; +import '../Platform/Platform'; +import '../Environment'; import { RenderBatch } from './RenderBatch/RenderBatch'; import { BrowserRenderer } from './BrowserRenderer'; import { toLogicalElement, LogicalElement } from './LogicalElements'; @@ -9,6 +9,7 @@ interface BrowserRendererRegistry { [browserRendererId: number]: BrowserRenderer; } const browserRenderers: BrowserRendererRegistry = {}; +let shouldResetScrollAfterNextBatch = false; export function attachRootComponentToLogicalElement(browserRendererId: number, logicalElement: LogicalElement, componentId: number): void { @@ -67,4 +68,20 @@ export function renderBatch(browserRendererId: number, batch: RenderBatch): void const eventHandlerId = batch.disposedEventHandlerIdsEntry(disposedEventHandlerIdsValues, i); browserRenderer.disposeEventHandler(eventHandlerId); } + + resetScrollIfNeeded(); +} + +export function resetScrollAfterNextBatch() { + shouldResetScrollAfterNextBatch = true; +} + +function resetScrollIfNeeded() { + if (shouldResetScrollAfterNextBatch) { + shouldResetScrollAfterNextBatch = false; + + // This assumes the scroller is on the window itself. There isn't a general way to know + // if some other element is playing the role of the primary scroll region. + window.scrollTo && window.scrollTo(0, 0); + } } diff --git a/src/Components/Web.JS/src/Rendering/RendererEventDispatcher.ts b/src/Components/Web.JS/src/Rendering/RendererEventDispatcher.ts new file mode 100644 index 0000000000..771be98074 --- /dev/null +++ b/src/Components/Web.JS/src/Rendering/RendererEventDispatcher.ts @@ -0,0 +1,18 @@ +import { EventDescriptor } from './BrowserRenderer'; +import { UIEventArgs } from './EventForDotNet'; + +type EventDispatcher = (eventDescriptor: EventDescriptor, eventArgs: UIEventArgs) => void; + +let eventDispatcherInstance: EventDispatcher; + +export function dispatchEvent(eventDescriptor: EventDescriptor, eventArgs: UIEventArgs): void { + if (!eventDispatcherInstance) { + throw new Error('eventDispatcher not initialized. Call \'setEventDispatcher\' to configure it.'); + } + + return eventDispatcherInstance(eventDescriptor, eventArgs); +} + +export function setEventDispatcher(newDispatcher: (eventDescriptor: EventDescriptor, eventArgs: UIEventArgs) => Promise): void { + eventDispatcherInstance = newDispatcher; +} diff --git a/src/Components/Web.JS/src/Services/UriHelper.ts b/src/Components/Web.JS/src/Services/NavigationManager.ts similarity index 83% rename from src/Components/Web.JS/src/Services/UriHelper.ts rename to src/Components/Web.JS/src/Services/NavigationManager.ts index 65d9d6cd36..3da8d11bef 100644 --- a/src/Components/Web.JS/src/Services/UriHelper.ts +++ b/src/Components/Web.JS/src/Services/NavigationManager.ts @@ -1,10 +1,11 @@ import '@dotnet/jsinterop'; +import { resetScrollAfterNextBatch } from '../Rendering/Renderer'; let hasRegisteredNavigationInterception = false; let hasRegisteredNavigationEventListeners = false; // Will be initialized once someone registers -let notifyLocationChangedCallback: { assemblyName: string; functionName: string } | null = null; +let notifyLocationChangedCallback: ((uri: string, intercepted: boolean) => Promise) | null = null; // These are the functions we're making available for invocation from .NET export const internalFunctions = { @@ -15,12 +16,12 @@ export const internalFunctions = { getLocationHref: () => location.href, }; -function listenForNavigationEvents(assemblyName: string, functionName: string) { +function listenForNavigationEvents(callback: (uri: string, intercepted: boolean) => Promise) { if (hasRegisteredNavigationEventListeners) { return; } - notifyLocationChangedCallback = { assemblyName, functionName }; + notifyLocationChangedCallback = callback; hasRegisteredNavigationEventListeners = true; window.addEventListener('popstate', () => notifyLocationChanged(false)); @@ -81,18 +82,20 @@ export function navigateTo(uri: string, forceLoad: boolean) { } function performInternalNavigation(absoluteInternalHref: string, interceptedLink: boolean) { + // Since this was *not* triggered by a back/forward gesture (that goes through a different + // code path starting with a popstate event), we don't want to preserve the current scroll + // position, so reset it. + // To avoid ugly flickering effects, we don't want to change the scroll position until the + // we render the new page. As a best approximation, wait until the next batch. + resetScrollAfterNextBatch(); + history.pushState(null, /* ignored title */ '', absoluteInternalHref); notifyLocationChanged(interceptedLink); } async function notifyLocationChanged(interceptedLink: boolean) { if (notifyLocationChangedCallback) { - await DotNet.invokeMethodAsync( - notifyLocationChangedCallback.assemblyName, - notifyLocationChangedCallback.functionName, - location.href, - interceptedLink - ); + await notifyLocationChangedCallback(location.href, interceptedLink); } } diff --git a/src/Components/Web.JS/tests/AutoReconnectCircuitHandler.test.ts b/src/Components/Web.JS/tests/AutoReconnectCircuitHandler.test.ts deleted file mode 100644 index 29b95bca76..0000000000 --- a/src/Components/Web.JS/tests/AutoReconnectCircuitHandler.test.ts +++ /dev/null @@ -1,78 +0,0 @@ - -import { AutoReconnectCircuitHandler } from "../src/Platform/Circuits/AutoReconnectCircuitHandler"; -import { UserSpecifiedDisplay } from "../src/Platform/Circuits/UserSpecifiedDisplay"; -import { DefaultReconnectDisplay } from "../src/Platform/Circuits/DefaultReconnectDisplay"; -import { ReconnectDisplay } from "../src/Platform/Circuits/ReconnectDisplay"; -import { NullLogger} from '../src/Platform/Logging/Loggers'; -import '../src/GlobalExports'; - -describe('AutoReconnectCircuitHandler', () => { - it('creates default element', () => { - const handler = new AutoReconnectCircuitHandler(NullLogger.instance); - - document.dispatchEvent(new Event('DOMContentLoaded')); - expect(handler.reconnectDisplay).toBeInstanceOf(DefaultReconnectDisplay); - }); - - it('locates user-specified handler', () => { - const element = document.createElement('div'); - element.id = 'components-reconnect-modal'; - document.body.appendChild(element); - const handler = new AutoReconnectCircuitHandler(NullLogger.instance); - - document.dispatchEvent(new Event('DOMContentLoaded')); - expect(handler.reconnectDisplay).toBeInstanceOf(UserSpecifiedDisplay); - - document.body.removeChild(element); - }); - - const TestDisplay = jest.fn(() => ({ - show: jest.fn(), - hide: jest.fn(), - failed: jest.fn() - })); - - it('hides display on connection up', () => { - const handler = new AutoReconnectCircuitHandler(NullLogger.instance); - const testDisplay = new TestDisplay(); - handler.reconnectDisplay = testDisplay; - - handler.onConnectionUp(); - - expect(testDisplay.hide).toHaveBeenCalled(); - - }); - - it('shows display on connection down', async () => { - const handler = new AutoReconnectCircuitHandler(NullLogger.instance); - handler.delay = () => Promise.resolve(); - const reconnect = jest.fn().mockResolvedValue(true); - window['Blazor'].reconnect = reconnect; - - const testDisplay = new TestDisplay(); - handler.reconnectDisplay = testDisplay; - - await handler.onConnectionDown(); - - expect(testDisplay.show).toHaveBeenCalled(); - expect(testDisplay.failed).not.toHaveBeenCalled(); - expect(reconnect).toHaveBeenCalledTimes(1); - }); - - it('invokes failed if reconnect fails', async () => { - const handler = new AutoReconnectCircuitHandler(NullLogger.instance); - handler.delay = () => Promise.resolve(); - const reconnect = jest.fn().mockRejectedValue(new Error('some error')); - window.console.error = jest.fn(); - window['Blazor'].reconnect = reconnect; - - const testDisplay = new TestDisplay(); - handler.reconnectDisplay = testDisplay; - - await handler.onConnectionDown(); - - expect(testDisplay.show).toHaveBeenCalled(); - expect(testDisplay.failed).toHaveBeenCalled(); - expect(reconnect).toHaveBeenCalledTimes(AutoReconnectCircuitHandler.MaxRetries); - }); -}); diff --git a/src/Components/Web.JS/tests/CircuitManager.test.ts b/src/Components/Web.JS/tests/CircuitManager.test.ts deleted file mode 100644 index 16017f19c4..0000000000 --- a/src/Components/Web.JS/tests/CircuitManager.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -(global as any).DotNet = { attachReviver: jest.fn() }; - -import { discoverPrerenderedCircuits } from '../src/Platform/Circuits/CircuitManager'; -import { JSDOM } from 'jsdom'; - -describe('CircuitManager', () => { - - it('discoverPrerenderedCircuits returns discovered prerendered circuits', () => { - const dom = new JSDOM(` - - - Page - - -
Preamble
- -

Prerendered content

- -
- - `); - - const results = discoverPrerenderedCircuits(dom.window.document); - - expect(results.length).toEqual(1); - expect(results[0].components.length).toEqual(1); - const result = results[0].components[0]; - expect(result.circuitId).toEqual("1234"); - expect(result.rendererId).toEqual(2); - expect(result.componentId).toEqual(1); - - }); - - it('discoverPrerenderedCircuits returns discovers multiple prerendered circuits', () => { - const dom = new JSDOM(` - - - Page - - -
Preamble
- -

Prerendered content

- -
- -

Prerendered content

- -
- - `); - - const results = discoverPrerenderedCircuits(dom.window.document); - - expect(results.length).toEqual(1); - expect(results[0].components.length).toEqual(2); - const first = results[0].components[0]; - expect(first.circuitId).toEqual("1234"); - expect(first.rendererId).toEqual(2); - expect(first.componentId).toEqual(1); - - const second = results[0].components[1]; - expect(second.circuitId).toEqual("1234"); - expect(second.rendererId).toEqual(2); - expect(second.componentId).toEqual(2); - }); - - it('discoverPrerenderedCircuits throws for malformed circuits - improper nesting', () => { - const dom = new JSDOM(` - - - Page - - -
Preamble
- -

Prerendered content

- -
- -

Prerendered content

- -
- - `); - - expect(() => discoverPrerenderedCircuits(dom.window.document)) - .toThrow(); - }); - - - it('discoverPrerenderedCircuits throws for malformed circuits - mixed string and int', () => { - const dom = new JSDOM(` - - - Page - - -
Preamble
- -

Prerendered content

- -
- -

Prerendered content

- -
- - `); - - expect(() => discoverPrerenderedCircuits(dom.window.document)) - .toThrow(); - }); - - it('discoverPrerenderedCircuits initializes circuits', () => { - const dom = new JSDOM(` - - - Page - - -
Preamble
- -

Prerendered content

- -
- -

Prerendered content

- -
- - `); - - const results = discoverPrerenderedCircuits(dom.window.document); - - for (let i = 0; i < results.length; i++) { - const result = results[i]; - for (let j = 0; j < result.components.length; j++) { - const component = result.components[j]; - component.initialize(); - } - } - - }); - -}); diff --git a/src/Components/Web.JS/tests/DefaultReconnectDisplay.test.ts b/src/Components/Web.JS/tests/DefaultReconnectDisplay.test.ts index 0dd77f63c2..bce5ca2588 100644 --- a/src/Components/Web.JS/tests/DefaultReconnectDisplay.test.ts +++ b/src/Components/Web.JS/tests/DefaultReconnectDisplay.test.ts @@ -1,18 +1,17 @@ import { DefaultReconnectDisplay } from "../src/Platform/Circuits/DefaultReconnectDisplay"; -import { AutoReconnectCircuitHandler } from "../src/Platform/Circuits/AutoReconnectCircuitHandler"; import {JSDOM} from 'jsdom'; describe('DefaultReconnectDisplay', () => { it ('adds element to the body on show', () => { const testDocument = new JSDOM().window.document; - const display = new DefaultReconnectDisplay(testDocument); + const display = new DefaultReconnectDisplay('test-dialog-id', testDocument); display.show(); const element = testDocument.body.querySelector('div'); expect(element).toBeDefined(); - expect(element!.id).toBe(AutoReconnectCircuitHandler.DialogId); + expect(element!.id).toBe('test-dialog-id'); expect(element!.style.display).toBe('block'); expect(display.message.textContent).toBe('Attempting to reconnect to the server...'); @@ -21,7 +20,7 @@ describe('DefaultReconnectDisplay', () => { it ('does not add element to the body multiple times', () => { const testDocument = new JSDOM().window.document; - const display = new DefaultReconnectDisplay(testDocument); + const display = new DefaultReconnectDisplay('test-dialog-id', testDocument); display.show(); display.show(); @@ -31,7 +30,7 @@ describe('DefaultReconnectDisplay', () => { it ('hides element', () => { const testDocument = new JSDOM().window.document; - const display = new DefaultReconnectDisplay(testDocument); + const display = new DefaultReconnectDisplay('test-dialog-id', testDocument); display.hide(); @@ -40,7 +39,7 @@ describe('DefaultReconnectDisplay', () => { it ('updates message on fail', () => { const testDocument = new JSDOM().window.document; - const display = new DefaultReconnectDisplay(testDocument); + const display = new DefaultReconnectDisplay('test-dialog-id', testDocument); display.show(); display.failed(); diff --git a/src/Components/Web.JS/tests/DefaultReconnectionHandler.test.ts b/src/Components/Web.JS/tests/DefaultReconnectionHandler.test.ts new file mode 100644 index 0000000000..62f207415e --- /dev/null +++ b/src/Components/Web.JS/tests/DefaultReconnectionHandler.test.ts @@ -0,0 +1,98 @@ +import '../src/GlobalExports'; +import { UserSpecifiedDisplay } from '../src/Platform/Circuits/UserSpecifiedDisplay'; +import { DefaultReconnectionHandler } from '../src/Platform/Circuits/DefaultReconnectionHandler'; +import { NullLogger} from '../src/Platform/Logging/Loggers'; +import { resolveOptions, ReconnectionOptions } from "../src/Platform/Circuits/BlazorOptions"; +import { ReconnectDisplay } from '../src/Platform/Circuits/ReconnectDisplay'; + +const defaultReconnectionOptions = resolveOptions().reconnectionOptions; + +describe('DefaultReconnectionHandler', () => { + it('toggles user-specified UI on disconnection/connection', () => { + const element = attachUserSpecifiedUI(defaultReconnectionOptions); + const handler = new DefaultReconnectionHandler(NullLogger.instance); + + // Shows on disconnection + handler.onConnectionDown(defaultReconnectionOptions); + expect(element.className).toBe(UserSpecifiedDisplay.ShowClassName); + + // Hides on reconnection + handler.onConnectionUp(); + expect(element.className).toBe(UserSpecifiedDisplay.HideClassName); + + document.body.removeChild(element); + }); + + it('hides display on connection up, and stops retrying', async () => { + const testDisplay = createTestDisplay(); + const reconnect = jest.fn().mockResolvedValue(true); + const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect); + + handler.onConnectionDown({ + maxRetries: 1000, + retryIntervalMilliseconds: 100, + dialogId: 'ignored' + }); + handler.onConnectionUp(); + + expect(testDisplay.hide).toHaveBeenCalled(); + await delay(200); + expect(reconnect).not.toHaveBeenCalled(); + }); + + it('shows display on connection down', async () => { + const testDisplay = createTestDisplay(); + const reconnect = jest.fn().mockResolvedValue(true); + const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect); + + handler.onConnectionDown({ + maxRetries: 1000, + retryIntervalMilliseconds: 100, + dialogId: 'ignored' + }); + expect(testDisplay.show).toHaveBeenCalled(); + expect(testDisplay.failed).not.toHaveBeenCalled(); + expect(reconnect).not.toHaveBeenCalled(); + + await delay(150); + expect(reconnect).toHaveBeenCalledTimes(1); + }); + + it('invokes failed if reconnect fails', async () => { + const testDisplay = createTestDisplay(); + const reconnect = jest.fn().mockRejectedValue(null); + const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect); + window.console.error = jest.fn(); + + handler.onConnectionDown({ + maxRetries: 3, + retryIntervalMilliseconds: 20, + dialogId: 'ignored' + }); + + await delay(100); + expect(testDisplay.show).toHaveBeenCalled(); + expect(testDisplay.failed).toHaveBeenCalled(); + expect(reconnect).toHaveBeenCalledTimes(3); + }); +}); + +function attachUserSpecifiedUI(options: ReconnectionOptions): Element { + const element = document.createElement('div'); + element.id = options.dialogId; + element.className = UserSpecifiedDisplay.HideClassName; + document.body.appendChild(element); + return element; +} + +function delay(durationMilliseconds: number) { + return new Promise(resolve => setTimeout(resolve, durationMilliseconds)); +} + +function createTestDisplay(): ReconnectDisplay { + return { + show: jest.fn(), + hide: jest.fn(), + failed: jest.fn() + }; +} diff --git a/src/Components/Web.JS/tests/RenderQueue.test.ts b/src/Components/Web.JS/tests/RenderQueue.test.ts index 653a0b24be..df22da3a8a 100644 --- a/src/Components/Web.JS/tests/RenderQueue.test.ts +++ b/src/Components/Web.JS/tests/RenderQueue.test.ts @@ -1,6 +1,6 @@ (global as any).DotNet = { attachReviver: jest.fn() }; -import RenderQueue from '../src/Platform/Circuits/RenderQueue'; +import { RenderQueue } from '../src/Platform/Circuits/RenderQueue'; import { NullLogger } from '../src/Platform/Logging/Loggers'; import * as signalR from '@aspnet/signalr'; @@ -25,14 +25,15 @@ describe('RenderQueue', () => { }); - it('processBatch does not render previous batches', () => { + it('processBatch acknowledges previously rendered batches', () => { const queue = RenderQueue.getOrCreateQueue(3, NullLogger.instance); const sendMock = jest.fn(); const connection = { send: sendMock } as any as signalR.HubConnection; - queue.processBatch(1, new Uint8Array(0), connection); + queue.processBatch(2, new Uint8Array(0), connection); - expect(sendMock.mock.calls.length).toEqual(0); + expect(sendMock.mock.calls.length).toEqual(1); + expect(queue.getLastBatchid()).toEqual(2); }); it('processBatch does not render out of order batches', () => { diff --git a/src/Components/Web.JS/yarn.lock b/src/Components/Web.JS/yarn.lock index c42251053e..f49df8df7d 100644 --- a/src/Components/Web.JS/yarn.lock +++ b/src/Components/Web.JS/yarn.lock @@ -99,6 +99,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.3.tgz#092d450db02bdb6ccb1ca8ffd47d8774a91aef87" integrity sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg== +"@babel/parser@^7.1.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" + integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== + "@babel/plugin-syntax-object-rest-spread@^7.0.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" @@ -139,15 +144,201 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@dotnet/jsinterop@3.0.0-preview6.19280.1": - version "3.0.0-preview6.19280.1" - resolved "https://dotnet.myget.org/F/aspnetcore-dev/npm/@dotnet/jsinterop/-/@dotnet/jsinterop-3.0.0-preview6.19280.1.tgz#4c991132f33157de93bc3b6db93cffc9e964b241" - integrity sha1-TJkRMvMxV96TvDttuTz/yelkskE= +"@cnakazawa/watch@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" + integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@dotnet/jsinterop@https://dotnet.myget.org/F/aspnetcore-dev/npm/@dotnet/jsinterop/-/@dotnet/jsinterop-3.0.0-preview8.19367.2.tgz": + version "3.0.0-preview8.19367.2" + resolved "https://dotnet.myget.org/F/aspnetcore-dev/npm/@dotnet/jsinterop/-/@dotnet/jsinterop-3.0.0-preview8.19367.2.tgz#885d87c9406ad0bbce878ff041d50342d03b2c86" + +"@jest/console@^24.7.1": + version "24.7.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" + integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg== + dependencies: + "@jest/source-map" "^24.3.0" + chalk "^2.0.1" + slash "^2.0.0" + +"@jest/core@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b" + integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A== + dependencies: + "@jest/console" "^24.7.1" + "@jest/reporters" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + ansi-escapes "^3.0.0" + chalk "^2.0.1" + exit "^0.1.2" + graceful-fs "^4.1.15" + jest-changed-files "^24.8.0" + jest-config "^24.8.0" + jest-haste-map "^24.8.0" + jest-message-util "^24.8.0" + jest-regex-util "^24.3.0" + jest-resolve-dependencies "^24.8.0" + jest-runner "^24.8.0" + jest-runtime "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" + jest-watcher "^24.8.0" + micromatch "^3.1.10" + p-each-series "^1.0.0" + pirates "^4.0.1" + realpath-native "^1.1.0" + rimraf "^2.5.4" + strip-ansi "^5.0.0" + +"@jest/environment@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac" + integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw== + dependencies: + "@jest/fake-timers" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + +"@jest/fake-timers@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1" + integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw== + dependencies: + "@jest/types" "^24.8.0" + jest-message-util "^24.8.0" + jest-mock "^24.8.0" + +"@jest/reporters@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729" + integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw== + dependencies: + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.2" + istanbul-lib-coverage "^2.0.2" + istanbul-lib-instrument "^3.0.1" + istanbul-lib-report "^2.0.4" + istanbul-lib-source-maps "^3.0.1" + istanbul-reports "^2.1.1" + jest-haste-map "^24.8.0" + jest-resolve "^24.8.0" + jest-runtime "^24.8.0" + jest-util "^24.8.0" + jest-worker "^24.6.0" + node-notifier "^5.2.1" + slash "^2.0.0" + source-map "^0.6.0" + string-length "^2.0.0" + +"@jest/source-map@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28" + integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + +"@jest/test-result@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3" + integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng== + dependencies: + "@jest/console" "^24.7.1" + "@jest/types" "^24.8.0" + "@types/istanbul-lib-coverage" "^2.0.0" + +"@jest/test-sequencer@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b" + integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg== + dependencies: + "@jest/test-result" "^24.8.0" + jest-haste-map "^24.8.0" + jest-runner "^24.8.0" + jest-runtime "^24.8.0" + +"@jest/transform@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5" + integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^24.8.0" + babel-plugin-istanbul "^5.1.0" + chalk "^2.0.1" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.1.15" + jest-haste-map "^24.8.0" + jest-regex-util "^24.3.0" + jest-util "^24.8.0" + micromatch "^3.1.10" + realpath-native "^1.1.0" + slash "^2.0.0" + source-map "^0.6.1" + write-file-atomic "2.4.1" + +"@jest/types@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad" + integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^12.0.9" "@microsoft/signalr@link:../../SignalR/clients/ts/signalr": version "0.0.0" uid "" +"@types/babel__core@^7.1.0": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" + integrity sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" + integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.7.tgz#2496e9ff56196cc1429c72034e07eab6121b6f3f" + integrity sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw== + dependencies: + "@babel/types" "^7.3.0" + "@types/emscripten@0.0.31": version "0.0.31" resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-0.0.31.tgz#160817d1324e8b7049604d39ac47d85eeeedd597" @@ -160,6 +351,26 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" + integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== + +"@types/istanbul-lib-report@*": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c" + integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" + integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/jest-diff@*": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" @@ -187,6 +398,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.5.tgz#011eece9d3f839a806b63973e228f85967b79ed3" integrity sha512-vVjM0SVzgaOUpflq4GYBvCpozes8OgIIS5gVXVka+OfK3hvnkC1i93U8WiY2OtNE4XUWyyy/86Kf6e0IHTQw1Q== +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + "@types/tough-cookie@*": version "2.3.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" @@ -197,6 +413,11 @@ resolved "https://registry.yarnpkg.com/@types/webassembly-js-api/-/webassembly-js-api-0.0.2.tgz#43a04bd75fa20332133c6c3986156bfeb4a3ced7" integrity sha512-htlxJRag6RUiMYUkS8Fjup+TMHO0VarpiF9MrqYaGJ0wXtIraQFz40rfA8VIeCiWy8sgpv3RLmigpgicG8fqGA== +"@types/yargs@^12.0.2", "@types/yargs@^12.0.9": + version "12.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" + integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== + "@typescript-eslint/eslint-plugin@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.5.0.tgz#85c509bcfc2eb35f37958fa677379c80b7a8f66f" @@ -224,150 +445,150 @@ lodash.unescape "4.0.1" semver "5.5.0" -"@webassemblyjs/ast@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.3.tgz#63a741bd715a6b6783f2ea5c6ab707516aa215eb" - integrity sha512-xy3m06+Iu4D32+6soz6zLnwznigXJRuFNTovBX2M4GqVqLb0dnyWLbPnpcXvUSdEN+9DVyDeaq2jyH1eIL2LZQ== +"@webassemblyjs/ast@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" + integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== dependencies: - "@webassemblyjs/helper-module-context" "1.8.3" - "@webassemblyjs/helper-wasm-bytecode" "1.8.3" - "@webassemblyjs/wast-parser" "1.8.3" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" -"@webassemblyjs/floating-point-hex-parser@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.3.tgz#f198a2d203b3c50846a064f5addd6a133ef9bc0e" - integrity sha512-vq1TISG4sts4f0lDwMUM0f3kpe0on+G3YyV5P0IySHFeaLKRYZ++n2fCFfG4TcCMYkqFeTUYFxm75L3ddlk2xA== +"@webassemblyjs/floating-point-hex-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" + integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== -"@webassemblyjs/helper-api-error@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.3.tgz#3b708f6926accd64dcbaa7ba5b63db5660ff4f66" - integrity sha512-BmWEynI4FnZbjk8CaYZXwcv9a6gIiu+rllRRouQUo73hglanXD3AGFJE7Q4JZCoVE0p5/jeX6kf5eKa3D4JxwQ== +"@webassemblyjs/helper-api-error@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" + integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== -"@webassemblyjs/helper-buffer@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.3.tgz#f3150a23ffaba68621e1f094c8a14bebfd53dd48" - integrity sha512-iVIMhWnNHoFB94+/2l7LpswfCsXeMRnWfExKtqsZ/E2NxZyUx9nTeKK/MEMKTQNEpyfznIUX06OchBHQ+VKi/Q== +"@webassemblyjs/helper-buffer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" + integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== -"@webassemblyjs/helper-code-frame@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.3.tgz#f43ac605789b519d95784ef350fd2968aebdd3ef" - integrity sha512-K1UxoJML7GKr1QXR+BG7eXqQkvu+eEeTjlSl5wUFQ6W6vaOc5OwSxTcb3oE9x/3+w4NHhrIKD4JXXCZmLdL2cg== +"@webassemblyjs/helper-code-frame@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" + integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== dependencies: - "@webassemblyjs/wast-printer" "1.8.3" + "@webassemblyjs/wast-printer" "1.8.5" -"@webassemblyjs/helper-fsm@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.3.tgz#46aaa03f41082a916850ebcb97e9fc198ef36a9c" - integrity sha512-387zipfrGyO77/qm7/SDUiZBjQ5KGk4qkrVIyuoubmRNIiqn3g+6ijY8BhnlGqsCCQX5bYKOnttJobT5xoyviA== +"@webassemblyjs/helper-fsm@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" + integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== -"@webassemblyjs/helper-module-context@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.3.tgz#150da405d90c8ea81ae0b0e1965b7b64e585634f" - integrity sha512-lPLFdQfaRssfnGEJit5Sk785kbBPPPK4ZS6rR5W/8hlUO/5v3F+rN8XuUcMj/Ny9iZiyKhhuinWGTUuYL4VKeQ== +"@webassemblyjs/helper-module-context@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" + integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== dependencies: - "@webassemblyjs/ast" "1.8.3" + "@webassemblyjs/ast" "1.8.5" mamacro "^0.0.3" -"@webassemblyjs/helper-wasm-bytecode@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.3.tgz#12f55bbafbbc7ddf9d8059a072cb7b0c17987901" - integrity sha512-R1nJW7bjyJLjsJQR5t3K/9LJ0QWuZezl8fGa49DZq4IVaejgvkbNlKEQxLYTC579zgT4IIIVHb5JA59uBPHXyw== +"@webassemblyjs/helper-wasm-bytecode@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" + integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== -"@webassemblyjs/helper-wasm-section@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.3.tgz#9e79456d9719e116f4f8998ee62ab54ba69a6cf3" - integrity sha512-P6F7D61SJY73Yz+fs49Q3+OzlYAZP86OfSpaSY448KzUy65NdfzDmo2NPVte+Rw4562MxEAacvq/mnDuvRWOcg== +"@webassemblyjs/helper-wasm-section@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" + integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-buffer" "1.8.3" - "@webassemblyjs/helper-wasm-bytecode" "1.8.3" - "@webassemblyjs/wasm-gen" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" -"@webassemblyjs/ieee754@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.3.tgz#0a89355b1f6c9d08d0605c2acbc2a6fe3141f5b4" - integrity sha512-UD4HuLU99hjIvWz1pD68b52qsepWQlYCxDYVFJQfHh3BHyeAyAlBJ+QzLR1nnS5J6hAzjki3I3AoJeobNNSZlg== +"@webassemblyjs/ieee754@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" + integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.3.tgz#b7fd9d7c039e34e375c4473bd4dc89ce8228b920" - integrity sha512-XXd3s1BmkC1gpGABuCRLqCGOD6D2L+Ma2BpwpjrQEHeQATKWAQtxAyU9Z14/z8Ryx6IG+L4/NDkIGHrccEhRUg== +"@webassemblyjs/leb128@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" + integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.3.tgz#75712db52cfdda868731569ddfe11046f1f1e7a2" - integrity sha512-Wv/WH9Zo5h5ZMyfCNpUrjFsLZ3X1amdfEuwdb7MLdG3cPAjRS6yc6ElULlpjLiiBTuzvmLhr3ENsuGyJ3wyCgg== +"@webassemblyjs/utf8@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" + integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== -"@webassemblyjs/wasm-edit@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.3.tgz#23c3c6206b096f9f6aa49623a5310a102ef0fb87" - integrity sha512-nB19eUx3Yhi1Vvv3yev5r+bqQixZprMtaoCs1brg9Efyl8Hto3tGaUoZ0Yb4Umn/gQCyoEGFfUxPLp1/8+Jvnw== +"@webassemblyjs/wasm-edit@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" + integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-buffer" "1.8.3" - "@webassemblyjs/helper-wasm-bytecode" "1.8.3" - "@webassemblyjs/helper-wasm-section" "1.8.3" - "@webassemblyjs/wasm-gen" "1.8.3" - "@webassemblyjs/wasm-opt" "1.8.3" - "@webassemblyjs/wasm-parser" "1.8.3" - "@webassemblyjs/wast-printer" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/helper-wasm-section" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-opt" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/wast-printer" "1.8.5" -"@webassemblyjs/wasm-gen@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.3.tgz#1a433b8ab97e074e6ac2e25fcbc8cb6125400813" - integrity sha512-sDNmu2nLBJZ/huSzlJvd9IK8B1EjCsOl7VeMV9VJPmxKYgTJ47lbkSP+KAXMgZWGcArxmcrznqm7FrAPQ7vVGg== +"@webassemblyjs/wasm-gen@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" + integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-wasm-bytecode" "1.8.3" - "@webassemblyjs/ieee754" "1.8.3" - "@webassemblyjs/leb128" "1.8.3" - "@webassemblyjs/utf8" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" -"@webassemblyjs/wasm-opt@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.3.tgz#54754bcf88f88e92b909416a91125301cc81419c" - integrity sha512-j8lmQVFR+FR4/645VNgV4R/Jz8i50eaPAj93GZyd3EIJondVshE/D9pivpSDIXyaZt+IkCodlzOoZUE4LnQbeA== +"@webassemblyjs/wasm-opt@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" + integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-buffer" "1.8.3" - "@webassemblyjs/wasm-gen" "1.8.3" - "@webassemblyjs/wasm-parser" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" -"@webassemblyjs/wasm-parser@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.3.tgz#d12ed19d1b8e8667a7bee040d2245aaaf215340b" - integrity sha512-NBI3SNNtRoy4T/KBsRZCAWUzE9lI94RH2nneLwa1KKIrt/2zzcTavWg6oY05ArCbb/PZDk3OUi63CD1RYtN65w== +"@webassemblyjs/wasm-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" + integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-api-error" "1.8.3" - "@webassemblyjs/helper-wasm-bytecode" "1.8.3" - "@webassemblyjs/ieee754" "1.8.3" - "@webassemblyjs/leb128" "1.8.3" - "@webassemblyjs/utf8" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" -"@webassemblyjs/wast-parser@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.3.tgz#44aa123e145503e995045dc3e5e2770069da117b" - integrity sha512-gZPst4CNcmGtKC1eYQmgCx6gwQvxk4h/nPjfPBbRoD+Raw3Hs+BS3yhrfgyRKtlYP+BJ8LcY9iFODEQofl2qbg== +"@webassemblyjs/wast-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" + integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/floating-point-hex-parser" "1.8.3" - "@webassemblyjs/helper-api-error" "1.8.3" - "@webassemblyjs/helper-code-frame" "1.8.3" - "@webassemblyjs/helper-fsm" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/floating-point-hex-parser" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-code-frame" "1.8.5" + "@webassemblyjs/helper-fsm" "1.8.5" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.3.tgz#b1177780b266b1305f2eeba87c4d6aa732352060" - integrity sha512-DTA6kpXuHK4PHu16yAD9QVuT1WZQRT7079oIFFmFSjqjLWGXS909I/7kiLTn931mcj7wGsaUNungjwNQ2lGQ3Q== +"@webassemblyjs/wast-printer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" + integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/wast-parser" "1.8.3" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -390,11 +611,6 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - acorn-globals@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" @@ -418,7 +634,7 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.5: +acorn@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== @@ -428,6 +644,11 @@ acorn@^6.0.7: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +acorn@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" + integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== + ajv-errors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" @@ -498,13 +719,6 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== - dependencies: - default-require-extensions "^2.0.0" - aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -603,13 +817,6 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== -async@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -630,13 +837,16 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -babel-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190" - integrity sha512-MLcagnVrO9ybQGLEfZUqnOzv36iQzU7Bj4elm39vCukumLVSfoX+tRy3/jW7lUKc7XdpRmB/jech6L/UCsSZjw== +babel-jest@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589" + integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw== dependencies: + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.1.0" + babel-preset-jest "^24.6.0" chalk "^2.4.2" slash "^2.0.0" @@ -649,18 +859,20 @@ babel-plugin-istanbul@^5.1.0: istanbul-lib-instrument "^3.0.0" test-exclude "^5.0.0" -babel-plugin-jest-hoist@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8" - integrity sha512-gljYrZz8w1b6fJzKcsfKsipSru2DU2DmQ39aB6nV3xQ0DDv3zpIzKGortA5gknrhNnPN8DweaEgrnZdmbGmhnw== +babel-plugin-jest-hoist@^24.6.0: + version "24.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz#f7f7f7ad150ee96d7a5e8e2c5da8319579e78019" + integrity sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w== + dependencies: + "@types/babel__traverse" "^7.0.6" -babel-preset-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e" - integrity sha512-FfNLDxFWsNX9lUmtwY7NheGlANnagvxq8LZdl5PKnVG3umP+S/g0XbVBfwtA4Ai3Ri/IMkWabBz3Tyk9wdspcw== +babel-preset-jest@^24.6.0: + version "24.6.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz#66f06136eefce87797539c0d63f1769cc3915984" + integrity sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw== dependencies: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.1.0" + babel-plugin-jest-hoist "^24.6.0" balanced-match@^1.0.0: version "1.0.0" @@ -908,19 +1120,19 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== -capture-exit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" - integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== dependencies: - rsvp "^3.3.3" + rsvp "^4.8.4" caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1009,6 +1221,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1056,11 +1277,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -compare-versions@^3.2.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== - component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -1158,7 +1374,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -1258,13 +1474,6 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= - dependencies: - strip-bom "^3.0.0" - define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1327,10 +1536,10 @@ detect-newline@^2.1.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= -diff-sequences@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" - integrity sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw== +diff-sequences@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" + integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw== diffie-hellman@^5.0.0: version "5.0.3" @@ -1408,7 +1617,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@4.1.0, enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== @@ -1600,12 +1809,10 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" +exec-sh@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" + integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg== execa@^1.0.0: version "1.0.0" @@ -1645,16 +1852,17 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2" - integrity sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw== +expect@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d" + integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA== dependencies: + "@jest/types" "^24.8.0" ansi-styles "^3.2.0" - jest-get-type "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" + jest-get-type "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" + jest-regex-util "^24.3.0" extend-shallow@^2.0.1: version "2.0.1" @@ -1750,14 +1958,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -fileset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1784,13 +1984,13 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= +findup-sync@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== dependencies: detect-file "^1.0.0" - is-glob "^3.1.0" + is-glob "^4.0.0" micromatch "^3.0.4" resolve-dir "^1.0.1" @@ -1872,7 +2072,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.3, fsevents@^1.2.7: +fsevents@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== @@ -1909,6 +2109,11 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -1936,7 +2141,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -1948,6 +2153,13 @@ glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +global-modules@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -1968,6 +2180,15 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + globals@^11.1.0, globals@^11.7.0: version "11.11.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" @@ -1983,7 +2204,7 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -handlebars@^4.1.0, handlebars@^4.1.2: +handlebars@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== @@ -2155,7 +2376,7 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^2.0.0: +import-local@2.0.0, import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== @@ -2191,7 +2412,7 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -2215,7 +2436,7 @@ inquirer@^6.2.2: strip-ansi "^5.0.0" through "^2.3.6" -interpret@^1.1.0: +interpret@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== @@ -2367,7 +2588,7 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -2440,38 +2661,12 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-api@^2.0.8: - version "2.1.1" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0" - integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw== - dependencies: - async "^2.6.1" - compare-versions "^3.2.1" - fileset "^2.0.3" - istanbul-lib-coverage "^2.0.3" - istanbul-lib-hook "^2.0.3" - istanbul-lib-instrument "^3.1.0" - istanbul-lib-report "^2.0.4" - istanbul-lib-source-maps "^3.0.2" - istanbul-reports "^2.1.1" - js-yaml "^3.12.0" - make-dir "^1.3.0" - minimatch "^3.0.4" - once "^1.4.0" - istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw== -istanbul-lib-hook@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" - integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA== - dependencies: - append-transform "^1.0.0" - -istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0: +istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971" integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA== @@ -2493,7 +2688,7 @@ istanbul-lib-report@^2.0.4: make-dir "^1.3.0" supports-color "^6.0.0" -istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2: +istanbul-lib-source-maps@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ== @@ -2511,341 +2706,364 @@ istanbul-reports@^2.1.1: dependencies: handlebars "^4.1.0" -jest-changed-files@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7" - integrity sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ== +jest-changed-files@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b" + integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug== dependencies: + "@jest/types" "^24.8.0" execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843" - integrity sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw== +jest-cli@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989" + integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA== dependencies: - ansi-escapes "^3.0.0" + "@jest/core" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.1.15" import-local "^2.0.0" is-ci "^2.0.0" - istanbul-api "^2.0.8" - istanbul-lib-coverage "^2.0.2" - istanbul-lib-instrument "^3.0.1" - istanbul-lib-source-maps "^3.0.1" - jest-changed-files "^24.0.0" - jest-config "^24.1.0" - jest-environment-jsdom "^24.0.0" - jest-get-type "^24.0.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve-dependencies "^24.1.0" - jest-runner "^24.1.0" - jest-runtime "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - jest-watcher "^24.0.0" - jest-worker "^24.0.0" - micromatch "^3.1.10" - node-notifier "^5.2.1" - p-each-series "^1.0.0" - pirates "^4.0.0" + jest-config "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" prompts "^2.0.1" - realpath-native "^1.0.0" - rimraf "^2.5.4" - slash "^2.0.0" - string-length "^2.0.0" - strip-ansi "^5.0.0" - which "^1.2.12" + realpath-native "^1.1.0" yargs "^12.0.2" -jest-config@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c" - integrity sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg== +jest-config@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f" + integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw== dependencies: "@babel/core" "^7.1.0" - babel-jest "^24.1.0" + "@jest/test-sequencer" "^24.8.0" + "@jest/types" "^24.8.0" + babel-jest "^24.8.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.0.0" - jest-environment-node "^24.0.0" - jest-get-type "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" + jest-environment-jsdom "^24.8.0" + jest-environment-node "^24.8.0" + jest-get-type "^24.8.0" + jest-jasmine2 "^24.8.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" micromatch "^3.1.10" - pretty-format "^24.0.0" - realpath-native "^1.0.2" + pretty-format "^24.8.0" + realpath-native "^1.1.0" -jest-diff@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34" - integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA== +jest-diff@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172" + integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g== dependencies: chalk "^2.0.1" - diff-sequences "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" + diff-sequences "^24.3.0" + jest-get-type "^24.8.0" + pretty-format "^24.8.0" -jest-docblock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e" - integrity sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA== +jest-docblock@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd" + integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg== dependencies: detect-newline "^2.1.0" -jest-each@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55" - integrity sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA== +jest-each@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775" + integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA== dependencies: + "@jest/types" "^24.8.0" chalk "^2.0.1" - jest-get-type "^24.0.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" + jest-get-type "^24.8.0" + jest-util "^24.8.0" + pretty-format "^24.8.0" -jest-environment-jsdom@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11" - integrity sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw== +jest-environment-jsdom@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857" + integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ== dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" + "@jest/environment" "^24.8.0" + "@jest/fake-timers" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + jest-util "^24.8.0" jsdom "^11.5.1" -jest-environment-node@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190" - integrity sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg== +jest-environment-node@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231" + integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q== dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" + "@jest/environment" "^24.8.0" + "@jest/fake-timers" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + jest-util "^24.8.0" -jest-get-type@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b" - integrity sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w== +jest-get-type@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc" + integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ== -jest-haste-map@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e" - integrity sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ== +jest-haste-map@^24.8.0: + version "24.8.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.1.tgz#f39cc1d2b1d907e014165b4bd5a957afcb992982" + integrity sha512-SwaxMGVdAZk3ernAx2Uv2sorA7jm3Kx+lR0grp6rMmnY06Kn/urtKx1LPN2mGTea4fCT38impYT28FfcLUhX0g== dependencies: + "@jest/types" "^24.8.0" + anymatch "^2.0.0" fb-watchman "^2.0.0" graceful-fs "^4.1.15" invariant "^2.2.4" - jest-serializer "^24.0.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" + jest-serializer "^24.4.0" + jest-util "^24.8.0" + jest-worker "^24.6.0" micromatch "^3.1.10" - sane "^3.0.0" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^1.2.7" -jest-jasmine2@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6" - integrity sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg== +jest-jasmine2@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898" + integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong== dependencies: "@babel/traverse" "^7.1.0" + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.1.0" + expect "^24.8.0" is-generator-fn "^2.0.0" - jest-each "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" + jest-each "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" + jest-runtime "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + pretty-format "^24.8.0" throat "^4.0.0" -jest-leak-detector@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6" - integrity sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg== +jest-leak-detector@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980" + integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g== dependencies: - pretty-format "^24.0.0" + pretty-format "^24.8.0" -jest-matcher-utils@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579" - integrity sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA== +jest-matcher-utils@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495" + integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw== dependencies: chalk "^2.0.1" - jest-diff "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" + jest-diff "^24.8.0" + jest-get-type "^24.8.0" + pretty-format "^24.8.0" -jest-message-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619" - integrity sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q== +jest-message-util@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b" + integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g== dependencies: "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" + "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d" - integrity sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A== - -jest-regex-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a" - integrity sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q== - -jest-resolve-dependencies@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c" - integrity sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw== +jest-mock@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56" + integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A== dependencies: - jest-regex-util "^24.0.0" - jest-snapshot "^24.1.0" + "@jest/types" "^24.8.0" -jest-resolve@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688" - integrity sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg== +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + +jest-regex-util@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" + integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== + +jest-resolve-dependencies@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0" + integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw== dependencies: + "@jest/types" "^24.8.0" + jest-regex-util "^24.3.0" + jest-snapshot "^24.8.0" + +jest-resolve@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f" + integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw== + dependencies: + "@jest/types" "^24.8.0" browser-resolve "^1.11.3" chalk "^2.0.1" - realpath-native "^1.0.0" + jest-pnp-resolver "^1.2.1" + realpath-native "^1.1.0" -jest-runner@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b" - integrity sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg== +jest-runner@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb" + integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow== dependencies: + "@jest/console" "^24.7.1" + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-docblock "^24.0.0" - jest-haste-map "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-leak-detector "^24.0.0" - jest-message-util "^24.0.0" - jest-runtime "^24.1.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" + jest-config "^24.8.0" + jest-docblock "^24.3.0" + jest-haste-map "^24.8.0" + jest-jasmine2 "^24.8.0" + jest-leak-detector "^24.8.0" + jest-message-util "^24.8.0" + jest-resolve "^24.8.0" + jest-runtime "^24.8.0" + jest-util "^24.8.0" + jest-worker "^24.6.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214" - integrity sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ== +jest-runtime@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620" + integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA== dependencies: - "@babel/core" "^7.1.0" - babel-plugin-istanbul "^5.1.0" + "@jest/console" "^24.7.1" + "@jest/environment" "^24.8.0" + "@jest/source-map" "^24.3.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + "@types/yargs" "^12.0.2" chalk "^2.0.1" - convert-source-map "^1.4.0" exit "^0.1.2" - fast-json-stable-stringify "^2.0.0" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - micromatch "^3.1.10" - realpath-native "^1.0.0" + jest-config "^24.8.0" + jest-haste-map "^24.8.0" + jest-message-util "^24.8.0" + jest-mock "^24.8.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" + realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" - write-file-atomic "2.4.1" yargs "^12.0.2" -jest-serializer@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b" - integrity sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw== +jest-serializer@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" + integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== -jest-snapshot@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b" - integrity sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA== +jest-snapshot@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6" + integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg== dependencies: "@babel/types" "^7.0.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" - jest-diff "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-resolve "^24.1.0" + expect "^24.8.0" + jest-diff "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" + jest-resolve "^24.8.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.0.0" + pretty-format "^24.8.0" semver "^5.5.0" -jest-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6" - integrity sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ== +jest-util@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1" + integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA== dependencies: + "@jest/console" "^24.7.1" + "@jest/fake-timers" "^24.8.0" + "@jest/source-map" "^24.3.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" callsites "^3.0.0" chalk "^2.0.1" graceful-fs "^4.1.15" is-ci "^2.0.0" - jest-message-util "^24.0.0" mkdirp "^0.5.1" slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020" - integrity sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g== +jest-validate@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849" + integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA== dependencies: + "@jest/types" "^24.8.0" camelcase "^5.0.0" chalk "^2.0.1" - jest-get-type "^24.0.0" + jest-get-type "^24.8.0" leven "^2.1.0" - pretty-format "^24.0.0" + pretty-format "^24.8.0" -jest-watcher@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890" - integrity sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g== +jest-watcher@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4" + integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw== dependencies: + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" + "@types/yargs" "^12.0.9" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.0.0" + jest-util "^24.8.0" string-length "^2.0.0" -jest-worker@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d" - integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg== +jest-worker@^24.6.0: + version "24.6.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" + integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== dependencies: merge-stream "^1.0.1" supports-color "^6.1.0" -jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2" - integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A== +jest@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.8.0.tgz#d5dff1984d0d1002196e9b7f12f75af1b2809081" + integrity sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg== dependencies: import-local "^2.0.0" - jest-cli "^24.1.0" + jest-cli "^24.8.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@^3.13.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3013,7 +3231,7 @@ loader-runner@^2.3.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== @@ -3041,9 +3259,9 @@ lodash.unescape@4.0.1: integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= lodash@^4.17.10, lodash@^4.17.11: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== loose-envify@^1.0.0: version "1.4.0" @@ -3135,11 +3353,6 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== - micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -3194,7 +3407,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.3, minimatch@^3.0.4: +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== @@ -3248,9 +3461,9 @@ mississippi@^3.0.0: through2 "^2.0.0" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -3583,7 +3796,7 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^3.0.0: +os-locale@^3.0.0, os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== @@ -3770,7 +3983,7 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= -pirates@^4.0.0: +pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== @@ -3799,13 +4012,15 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -pretty-format@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591" - integrity sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g== +pretty-format@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" + integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== dependencies: + "@jest/types" "^24.8.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" + react-is "^16.8.4" process-nextick-args@~2.0.0: version "2.0.0" @@ -3942,6 +4157,11 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-is@^16.8.4: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" + integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== + read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -3981,7 +4201,7 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -realpath-native@^1.0.0, realpath-native@^1.0.2: +realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== @@ -4068,6 +4288,11 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + requireindex@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" @@ -4148,10 +4373,10 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rsvp@^3.3.3: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== run-async@^2.2.0: version "2.3.0" @@ -4191,22 +4416,20 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sane@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" - integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q== +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== dependencies: + "@cnakazawa/watch" "^1.0.3" anymatch "^2.0.0" - capture-exit "^1.2.0" - exec-sh "^0.2.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" execa "^1.0.0" fb-watchman "^2.0.0" micromatch "^3.1.4" minimist "^1.1.1" walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" sax@^1.2.4: version "1.2.4" @@ -4247,20 +4470,10 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== +set-value@^0.4.3, set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -4525,7 +4738,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -4569,7 +4782,7 @@ strip-ansi@^5.0.0: dependencies: ansi-regex "^4.0.0" -strip-ansi@^5.1.0: +strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -4591,20 +4804,20 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -supports-color@^5.3.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.0.0, supports-color@^6.1.0: +supports-color@6.1.0, supports-color@^6.0.0, supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== dependencies: has-flag "^3.0.0" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -4843,10 +5056,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.1.tgz#b6691be11a881ffa9a05765a205cb7383f3b63c6" - integrity sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q== +typescript@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" + integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== uglify-js@^3.1.4: version "3.4.9" @@ -4958,10 +5171,10 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -v8-compile-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== +v8-compile-cache@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" + integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -4994,21 +5207,13 @@ w3c-hr-time@^1.0.1: dependencies: browser-process-hrtime "^0.1.2" -walker@~1.0.5: +walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= dependencies: makeerror "1.0.x" -watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= - dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" - watchpack@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -5023,22 +5228,22 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-cli@^3.0.8: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" - integrity sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q== +webpack-cli@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.6.tgz#2c8c399a2642133f8d736a359007a052e060032c" + integrity sha512-0vEa83M7kJtxK/jUhlpZ27WHIOndz5mghWL2O53kiDoA9DIxSKnfqB92LoqEn77cT4f3H2cZm1BMEat/6AZz3A== dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.0" - findup-sync "^2.0.0" - global-modules "^1.0.0" - import-local "^2.0.0" - interpret "^1.1.0" - loader-utils "^1.1.0" - supports-color "^5.5.0" - v8-compile-cache "^2.0.2" - yargs "^12.0.4" + chalk "2.4.2" + cross-spawn "6.0.5" + enhanced-resolve "4.1.0" + findup-sync "3.0.0" + global-modules "2.0.0" + import-local "2.0.0" + interpret "1.2.0" + loader-utils "1.2.3" + supports-color "6.1.0" + v8-compile-cache "2.0.3" + yargs "13.2.4" webpack-sources@^1.1.0, webpack-sources@^1.3.0: version "1.3.0" @@ -5048,17 +5253,16 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.12.0: - version "4.29.5" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.5.tgz#52b60a7b0838427c3a894cd801a11dc0836bc79f" - integrity sha512-DuWlYUT982c7XVHodrLO9quFbNpVq5FNxLrMUfYUTlgKW0+yPimynYf1kttSQpEneAL1FH3P3OLNgkyImx8qIQ== +webpack@^4.36.1: + version "4.36.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.36.1.tgz#f546fda7a403a76faeaaa7196c50d12370ed18a9" + integrity sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg== dependencies: - "@webassemblyjs/ast" "1.8.3" - "@webassemblyjs/helper-module-context" "1.8.3" - "@webassemblyjs/wasm-edit" "1.8.3" - "@webassemblyjs/wasm-parser" "1.8.3" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.2.0" ajv "^6.1.0" ajv-keywords "^3.1.0" chrome-trace-event "^1.0.0" @@ -5113,7 +5317,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: +which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -5152,6 +5356,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -5222,7 +5435,32 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^12.0.2, yargs@^12.0.4: +yargs-parser@^13.1.0: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" + +yargs@^12.0.2: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== diff --git a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs index 221a74b072..034b500218 100644 --- a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs +++ b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs @@ -1,6 +1,425 @@ // Copyright (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 +{ + [Microsoft.AspNetCore.Components.BindElementAttribute("select", null, "value", "onchange")] + [Microsoft.AspNetCore.Components.BindElementAttribute("textarea", null, "value", "onchange")] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange", false, null)] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", "value", "value", "onchange", true, "yyyy-MM-dd")] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", null, "value", "onchange", true, "yyyy-MM-dd")] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", "value", "value", "onchange", true, null)] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", null, "value", "onchange", true, null)] + [Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange", false, null)] + [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange", false, null)] + [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange", false, null)] + public static partial class BindAttributes + { + } + [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.Class, AllowMultiple=true, Inherited=true)] + public sealed partial class BindInputElementAttribute : System.Attribute + { + public BindInputElementAttribute(string type, string suffix, string valueAttribute, string changeAttribute, bool isInvariantCulture, string format) { } + public string ChangeAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Format { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public bool IsInvariantCulture { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Suffix { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + } + public partial class DataTransfer + { + public DataTransfer() { } + public string DropEffect { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string EffectAllowed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string[] Files { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Components.UIDataTransferItem[] Items { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string[] Types { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public sealed partial class EventHandlerAttribute : System.Attribute + { + public EventHandlerAttribute(string attributeName, System.Type eventArgsType) { } + public string AttributeName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public System.Type EventArgsType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + } + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onabort", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onactivate", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforeactivate", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforecopy", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforecut", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforedeactivate", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onbeforepaste", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onblur", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncanplay", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncanplaythrough", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onchange", typeof(Microsoft.AspNetCore.Components.ChangeEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onclick", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncontextmenu", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncopy", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncuechange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oncut", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondblclick", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondeactivate", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondrag", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragend", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragenter", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragleave", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragover", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondragstart", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondrop", typeof(Microsoft.AspNetCore.Components.UIDragEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ondurationchange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onemptied", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onended", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onerror", typeof(Microsoft.AspNetCore.Components.UIErrorEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocus", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocusin", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfocusout", typeof(Microsoft.AspNetCore.Components.UIFocusEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfullscreenchange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onfullscreenerror", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ongotpointercapture", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oninput", typeof(Microsoft.AspNetCore.Components.ChangeEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("oninvalid", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeydown", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeypress", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onkeyup", typeof(Microsoft.AspNetCore.Components.UIKeyboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onload", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadeddata", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadedmetadata", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadend", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onloadstart", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onlostpointercapture", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousedown", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousemove", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseout", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseover", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmouseup", typeof(Microsoft.AspNetCore.Components.UIMouseEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onmousewheel", typeof(Microsoft.AspNetCore.Components.UIWheelEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpaste", typeof(Microsoft.AspNetCore.Components.UIClipboardEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpause", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onplay", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onplaying", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointercancel", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerdown", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerenter", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerleave", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerlockchange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerlockerror", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointermove", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerout", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerover", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onpointerup", typeof(Microsoft.AspNetCore.Components.UIPointerEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onprogress", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onratechange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onreadystatechange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onreset", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onscroll", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onseeked", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onseeking", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselect", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselectionchange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onselectstart", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onstalled", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onstop", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onsubmit", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onsuspend", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontimeout", typeof(Microsoft.AspNetCore.Components.UIProgressEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontimeupdate", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchcancel", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchend", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchenter", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchleave", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchmove", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("ontouchstart", typeof(Microsoft.AspNetCore.Components.UITouchEventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onvolumechange", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onwaiting", typeof(System.EventArgs))] + [Microsoft.AspNetCore.Components.EventHandlerAttribute("onwheel", typeof(Microsoft.AspNetCore.Components.UIWheelEventArgs))] + public static partial class EventHandlers + { + } + public partial class UIClipboardEventArgs : System.EventArgs + { + public UIClipboardEventArgs() { } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIDataTransferItem + { + public UIDataTransferItem() { } + public string Kind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIDragEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs + { + public UIDragEventArgs() { } + public Microsoft.AspNetCore.Components.DataTransfer DataTransfer { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIErrorEventArgs : System.EventArgs + { + public UIErrorEventArgs() { } + public int Colno { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Filename { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public int Lineno { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Message { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIFocusEventArgs : System.EventArgs + { + public UIFocusEventArgs() { } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIKeyboardEventArgs : System.EventArgs + { + public UIKeyboardEventArgs() { } + public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Code { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Key { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public float Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool Repeat { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIMouseEventArgs : System.EventArgs + { + public UIMouseEventArgs() { } + public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Button { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Buttons { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ClientX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ClientY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Detail { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ScreenX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ScreenY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIPointerEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs + { + public UIPointerEventArgs() { } + public float Height { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool IsPrimary { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long PointerId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string PointerType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public float Pressure { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public float TiltX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public float TiltY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public float Width { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIProgressEventArgs : System.EventArgs + { + public UIProgressEventArgs() { } + public bool LengthComputable { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Loaded { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Total { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UITouchEventArgs : System.EventArgs + { + public UITouchEventArgs() { } + public bool AltKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Components.UITouchPoint[] ChangedTouches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool CtrlKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Detail { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool MetaKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public bool ShiftKey { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Components.UITouchPoint[] TargetTouches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Components.UITouchPoint[] Touches { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UITouchPoint + { + public UITouchPoint() { } + public double ClientX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ClientY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public long Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double PageX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double PageY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ScreenX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double ScreenY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public partial class UIWheelEventArgs : Microsoft.AspNetCore.Components.UIMouseEventArgs + { + public UIWheelEventArgs() { } + public long DeltaMode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double DeltaX { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double DeltaY { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public double DeltaZ { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + } + public static partial class WebEventCallbackFactoryUIEventArgsExtensions + { + 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.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.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.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.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; } + 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; } + 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; } + 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; } + 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; } + } +} +namespace Microsoft.AspNetCore.Components.Forms +{ + public static partial class EditContextFieldClassExtensions + { + public static string FieldCssClass(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, in Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) { throw null; } + public static string FieldCssClass(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, System.Linq.Expressions.Expression> accessor) { throw null; } + } + public partial class EditForm : Microsoft.AspNetCore.Components.ComponentBase + { + public EditForm() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [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.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.EventCallback OnInvalidSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.EventCallback OnSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.EventCallback OnValidSubmit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override void OnParametersSet() { } + } + public abstract partial class InputBase : Microsoft.AspNetCore.Components.ComponentBase + { + protected InputBase() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected string CssClass { get { throw null; } } + protected T CurrentValue { get { throw null; } set { } } + protected string CurrentValueAsString { get { throw null; } set { } } + protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public T Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.EventCallback ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Linq.Expressions.Expression> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected virtual string FormatValueAsString(T value) { throw null; } + public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } + protected abstract bool TryParseValueFromString(string value, out T result, out string validationErrorMessage); + } + public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputCheckbox() { } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override bool TryParseValueFromString(string value, out bool result, out string validationErrorMessage) { throw null; } + } + public partial class InputDate : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputDate() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override string FormatValueAsString(T value) { throw null; } + protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } + } + public partial class InputNumber : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputNumber() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override string FormatValueAsString(T value) { throw null; } + protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } + } + public partial class InputSelect : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputSelect() { } + [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.RenderTree.RenderTreeBuilder builder) { } + protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw null; } + } + public partial class InputText : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputText() { } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) { throw null; } + } + public partial class InputTextArea : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputTextArea() { } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) { throw null; } + } + public partial class ValidationMessage : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable + { + public ValidationMessage() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Linq.Expressions.Expression> For { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected virtual void Dispose(bool disposing) { } + protected override void OnParametersSet() { } + void System.IDisposable.Dispose() { } + } + public partial class ValidationSummary : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable + { + public ValidationSummary() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected virtual void Dispose(bool disposing) { } + protected override void OnParametersSet() { } + void System.IDisposable.Dispose() { } + } +} +namespace Microsoft.AspNetCore.Components.Routing +{ + public partial class NavLink : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable + { + public NavLink() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string ActiveClass { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { [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 { } } + protected string CssClass { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.Routing.NavLinkMatch Match { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + public void Dispose() { } + protected override void OnInitialized() { } + protected override void OnParametersSet() { } + } + public enum NavLinkMatch + { + Prefix = 0, + All = 1, + } +} namespace Microsoft.AspNetCore.Components.Web { public static partial class RendererRegistryEventDispatcher diff --git a/src/Components/Components/src/BindAttributes.cs b/src/Components/Web/src/BindAttributes.cs similarity index 50% rename from src/Components/Components/src/BindAttributes.cs rename to src/Components/Web/src/BindAttributes.cs index 258ca0e1f0..91a1ee894c 100644 --- a/src/Components/Components/src/BindAttributes.cs +++ b/src/Components/Web/src/BindAttributes.cs @@ -7,20 +7,28 @@ namespace Microsoft.AspNetCore.Components /// Infrastructure for the discovery of bind attributes for markup elements. ///
/// - /// To extend the set of bind attributes, define a public class named + /// To extend the set of bind attributes, define a public class named /// BindAttributes and annotate it with the appropriate attributes. /// - + // Handles cases like - this is a fallback and will be ignored // when a specific type attribute is applied. - [BindInputElement(null, null, "value", "onchange")] + [BindInputElement(null, null, "value", "onchange", isInvariantCulture: false, format: null)] // Handles cases like - this is a fallback and will be ignored // when a specific type attribute is applied. - [BindInputElement(null, "value", "value", "onchange")] + [BindInputElement(null, "value", "value", "onchange", isInvariantCulture: false, format: null)] - [BindInputElement("checkbox", null, "checked", "onchange")] - [BindInputElement("text", null, "value", "onchange")] + [BindInputElement("checkbox", null, "checked", "onchange", isInvariantCulture: false, format: null)] + [BindInputElement("text", null, "value", "onchange", isInvariantCulture: false, format: null)] + + // type="number" is invariant culture + [BindInputElement("number", null, "value", "onchange", isInvariantCulture: true, format: null)] + [BindInputElement("number", "value", "value", "onchange", isInvariantCulture: true, format: null)] + + // type="date" is invariant culture with a specific format + [BindInputElement("date", null, "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")] + [BindInputElement("date", "value", "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")] [BindElement("select", null, "value", "onchange")] [BindElement("textarea", null, "value", "onchange")] diff --git a/src/Components/Components/src/BindElementAttribute.cs b/src/Components/Web/src/BindElementAttribute.cs similarity index 100% rename from src/Components/Components/src/BindElementAttribute.cs rename to src/Components/Web/src/BindElementAttribute.cs diff --git a/src/Components/Components/src/BindInputElementAttribute.cs b/src/Components/Web/src/BindInputElementAttribute.cs similarity index 67% rename from src/Components/Components/src/BindInputElementAttribute.cs rename to src/Components/Web/src/BindInputElementAttribute.cs index fe618ca7bb..0cba1a8e84 100644 --- a/src/Components/Components/src/BindInputElementAttribute.cs +++ b/src/Components/Web/src/BindInputElementAttribute.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (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; namespace Microsoft.AspNetCore.Components { @@ -18,7 +19,13 @@ namespace Microsoft.AspNetCore.Components /// The suffix value. /// The name of the value attribute to be bound. /// The name of an attribute that will register an associated change event. - public BindInputElementAttribute(string type, string suffix, string valueAttribute, string changeAttribute) + /// + /// Determines whether binding will use or . + /// + /// + /// An optional format to use when converting values. + /// + public BindInputElementAttribute(string type, string suffix, string valueAttribute, string changeAttribute, bool isInvariantCulture, string format) { if (valueAttribute == null) { @@ -34,6 +41,8 @@ namespace Microsoft.AspNetCore.Components Suffix = suffix; ValueAttribute = valueAttribute; ChangeAttribute = changeAttribute; + IsInvariantCulture = isInvariantCulture; + Format = format; } /// @@ -55,5 +64,16 @@ namespace Microsoft.AspNetCore.Components /// Gets the name of an attribute that will register an associated change event. /// public string ChangeAttribute { get; } + + /// + /// Gets a value that determines whether binding will use or + /// . + /// + public bool IsInvariantCulture { get; } + + /// + /// Gets an optional format to use when converting values. + /// + public string Format { get; } } } diff --git a/src/Components/Web/src/BrowserUriHelperInterop.cs b/src/Components/Web/src/BrowserNavigationManagerInterop.cs similarity index 79% rename from src/Components/Web/src/BrowserUriHelperInterop.cs rename to src/Components/Web/src/BrowserNavigationManagerInterop.cs index 3a22d5a4af..ddb3794b19 100644 --- a/src/Components/Web/src/BrowserUriHelperInterop.cs +++ b/src/Components/Web/src/BrowserNavigationManagerInterop.cs @@ -4,11 +4,9 @@ namespace Microsoft.AspNetCore.Components.Web { // Shared interop constants - internal static class BrowserUriHelperInterop + internal static class BrowserNavigationManagerInterop { - private static readonly string Prefix = "Blazor._internal.uriHelper."; - - public static readonly string ListenForNavigationEvents = Prefix + "listenForNavigationEvents"; + private static readonly string Prefix = "Blazor._internal.navigationManager."; public static readonly string EnableNavigationInterception = Prefix + "enableNavigationInterception"; diff --git a/src/Components/Web/src/DataTransfer.cs b/src/Components/Web/src/DataTransfer.cs new file mode 100644 index 0000000000..5cf8ee7dd8 --- /dev/null +++ b/src/Components/Web/src/DataTransfer.cs @@ -0,0 +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. + +namespace Microsoft.AspNetCore.Components +{ + /// + /// The object is used to hold the data that is being dragged during a drag and drop operation. + /// It may hold one or more , each of one or more data types. + /// For more information about drag and drop, see HTML Drag and Drop API. + /// + public class DataTransfer + { + /// + /// Gets the type of drag-and-drop operation currently selected or sets the operation to a new type. + /// The value must be none, copy, link or move. + /// + public string DropEffect { get; set; } + + /// + /// Provides all of the types of operations that are possible. + /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized. + /// + public string EffectAllowed { get; set; } + + /// + /// Contains a list of all the local files available on the data transfer. + /// If the drag operation doesn't involve dragging files, this property is an empty list. + /// + public string[] Files { get; set; } + + /// + /// Gives a array which is a list of all of the drag data. + /// + public UIDataTransferItem[] Items { get; set; } + + /// + /// An array of giving the formats that were set in the dragstart event. + /// + public string[] Types { get; set; } + } +} diff --git a/src/Components/Components/src/EventHandlerAttribute.cs b/src/Components/Web/src/EventHandlerAttribute.cs similarity index 100% rename from src/Components/Components/src/EventHandlerAttribute.cs rename to src/Components/Web/src/EventHandlerAttribute.cs diff --git a/src/Components/Components/src/EventHandlers.cs b/src/Components/Web/src/EventHandlers.cs similarity index 61% rename from src/Components/Components/src/EventHandlers.cs rename to src/Components/Web/src/EventHandlers.cs index de0d20a544..8df8102278 100644 --- a/src/Components/Components/src/EventHandlers.cs +++ b/src/Components/Web/src/EventHandlers.cs @@ -43,24 +43,24 @@ namespace Microsoft.AspNetCore.Components [EventHandler("onkeypress", typeof(UIKeyboardEventArgs))] // Input events - [EventHandler("onchange", typeof(UIChangeEventArgs))] - [EventHandler("oninput", typeof(UIChangeEventArgs))] - [EventHandler("oninvalid", typeof(UIEventArgs))] - [EventHandler("onreset", typeof(UIEventArgs))] - [EventHandler("onselect", typeof(UIEventArgs))] - [EventHandler("onselectstart", typeof(UIEventArgs))] - [EventHandler("onselectionchange", typeof(UIEventArgs))] - [EventHandler("onsubmit", typeof(UIEventArgs))] + [EventHandler("onchange", typeof(ChangeEventArgs))] + [EventHandler("oninput", typeof(ChangeEventArgs))] + [EventHandler("oninvalid", typeof(EventArgs))] + [EventHandler("onreset", typeof(EventArgs))] + [EventHandler("onselect", typeof(EventArgs))] + [EventHandler("onselectstart", typeof(EventArgs))] + [EventHandler("onselectionchange", typeof(EventArgs))] + [EventHandler("onsubmit", typeof(EventArgs))] // Clipboard events - [EventHandler("onbeforecopy", typeof(UIEventArgs))] - [EventHandler("onbeforecut", typeof(UIEventArgs))] - [EventHandler("onbeforepaste", typeof(UIEventArgs))] + [EventHandler("onbeforecopy", typeof(EventArgs))] + [EventHandler("onbeforecut", typeof(EventArgs))] + [EventHandler("onbeforepaste", typeof(EventArgs))] [EventHandler("oncopy", typeof(UIClipboardEventArgs))] [EventHandler("oncut", typeof(UIClipboardEventArgs))] [EventHandler("onpaste", typeof(UIClipboardEventArgs))] - // Touch events + // Touch events [EventHandler("ontouchcancel", typeof(UITouchEventArgs))] [EventHandler("ontouchend", typeof(UITouchEventArgs))] [EventHandler("ontouchmove", typeof(UITouchEventArgs))] @@ -81,23 +81,23 @@ namespace Microsoft.AspNetCore.Components [EventHandler("onpointerup", typeof(UIPointerEventArgs))] // Media events - [EventHandler("oncanplay", typeof(UIEventArgs))] - [EventHandler("oncanplaythrough", typeof(UIEventArgs))] - [EventHandler("oncuechange", typeof(UIEventArgs))] - [EventHandler("ondurationchange", typeof(UIEventArgs))] - [EventHandler("onemptied", typeof(UIEventArgs))] - [EventHandler("onpause", typeof(UIEventArgs))] - [EventHandler("onplay", typeof(UIEventArgs))] - [EventHandler("onplaying", typeof(UIEventArgs))] - [EventHandler("onratechange", typeof(UIEventArgs))] - [EventHandler("onseeked", typeof(UIEventArgs))] - [EventHandler("onseeking", typeof(UIEventArgs))] - [EventHandler("onstalled", typeof(UIEventArgs))] - [EventHandler("onstop", typeof(UIEventArgs))] - [EventHandler("onsuspend", typeof(UIEventArgs))] - [EventHandler("ontimeupdate", typeof(UIEventArgs))] - [EventHandler("onvolumechange", typeof(UIEventArgs))] - [EventHandler("onwaiting", typeof(UIEventArgs))] + [EventHandler("oncanplay", typeof(EventArgs))] + [EventHandler("oncanplaythrough", typeof(EventArgs))] + [EventHandler("oncuechange", typeof(EventArgs))] + [EventHandler("ondurationchange", typeof(EventArgs))] + [EventHandler("onemptied", typeof(EventArgs))] + [EventHandler("onpause", typeof(EventArgs))] + [EventHandler("onplay", typeof(EventArgs))] + [EventHandler("onplaying", typeof(EventArgs))] + [EventHandler("onratechange", typeof(EventArgs))] + [EventHandler("onseeked", typeof(EventArgs))] + [EventHandler("onseeking", typeof(EventArgs))] + [EventHandler("onstalled", typeof(EventArgs))] + [EventHandler("onstop", typeof(EventArgs))] + [EventHandler("onsuspend", typeof(EventArgs))] + [EventHandler("ontimeupdate", typeof(EventArgs))] + [EventHandler("onvolumechange", typeof(EventArgs))] + [EventHandler("onwaiting", typeof(EventArgs))] // Progress events [EventHandler("onloadstart", typeof(UIProgressEventArgs))] @@ -109,19 +109,19 @@ namespace Microsoft.AspNetCore.Components [EventHandler("onerror", typeof(UIErrorEventArgs))] // General events - [EventHandler("onactivate", typeof(UIEventArgs))] - [EventHandler("onbeforeactivate", typeof(UIEventArgs))] - [EventHandler("onbeforedeactivate", typeof(UIEventArgs))] - [EventHandler("ondeactivate", typeof(UIEventArgs))] - [EventHandler("onended", typeof(UIEventArgs))] - [EventHandler("onfullscreenchange", typeof(UIEventArgs))] - [EventHandler("onfullscreenerror", typeof(UIEventArgs))] - [EventHandler("onloadeddata", typeof(UIEventArgs))] - [EventHandler("onloadedmetadata", typeof(UIEventArgs))] - [EventHandler("onpointerlockchange", typeof(UIEventArgs))] - [EventHandler("onpointerlockerror", typeof(UIEventArgs))] - [EventHandler("onreadystatechange", typeof(UIEventArgs))] - [EventHandler("onscroll", typeof(UIEventArgs))] + [EventHandler("onactivate", typeof(EventArgs))] + [EventHandler("onbeforeactivate", typeof(EventArgs))] + [EventHandler("onbeforedeactivate", typeof(EventArgs))] + [EventHandler("ondeactivate", typeof(EventArgs))] + [EventHandler("onended", typeof(EventArgs))] + [EventHandler("onfullscreenchange", typeof(EventArgs))] + [EventHandler("onfullscreenerror", typeof(EventArgs))] + [EventHandler("onloadeddata", typeof(EventArgs))] + [EventHandler("onloadedmetadata", typeof(EventArgs))] + [EventHandler("onpointerlockchange", typeof(EventArgs))] + [EventHandler("onpointerlockerror", typeof(EventArgs))] + [EventHandler("onreadystatechange", typeof(EventArgs))] + [EventHandler("onscroll", typeof(EventArgs))] public static class EventHandlers { } diff --git a/src/Components/Components/src/Forms/EditContextFieldClassExtensions.cs b/src/Components/Web/src/Forms/EditContextFieldClassExtensions.cs similarity index 81% rename from src/Components/Components/src/Forms/EditContextFieldClassExtensions.cs rename to src/Components/Web/src/Forms/EditContextFieldClassExtensions.cs index bd92563535..687328043a 100644 --- a/src/Components/Components/src/Forms/EditContextFieldClassExtensions.cs +++ b/src/Components/Web/src/Forms/EditContextFieldClassExtensions.cs @@ -14,23 +14,23 @@ namespace Microsoft.AspNetCore.Components.Forms public static class EditContextFieldClassExtensions { /// - /// Gets a string that indicates the status of the specified field. This will include + /// Gets a string that indicates the status of the specified field as a CSS class. This will include /// some combination of "modified", "valid", or "invalid", depending on the status of the field. /// /// The . /// An identifier for the field. /// A string that indicates the status of the field. - public static string FieldClass(this EditContext editContext, Expression> accessor) - => FieldClass(editContext, FieldIdentifier.Create(accessor)); + public static string FieldCssClass(this EditContext editContext, Expression> accessor) + => FieldCssClass(editContext, FieldIdentifier.Create(accessor)); /// - /// Gets a string that indicates the status of the specified field. This will include + /// Gets a string that indicates the status of the specified field as a CSS class. This will include /// some combination of "modified", "valid", or "invalid", depending on the status of the field. /// /// The . /// An identifier for the field. /// A string that indicates the status of the field. - public static string FieldClass(this EditContext editContext, in FieldIdentifier fieldIdentifier) + public static string FieldCssClass(this EditContext editContext, in FieldIdentifier fieldIdentifier) { var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any(); if (editContext.IsModified(fieldIdentifier)) diff --git a/src/Components/Components/src/Forms/EditForm.cs b/src/Components/Web/src/Forms/EditForm.cs similarity index 93% rename from src/Components/Components/src/Forms/EditForm.cs rename to src/Components/Web/src/Forms/EditForm.cs index 89a329165b..4a0e490dcf 100644 --- a/src/Components/Components/src/Forms/EditForm.cs +++ b/src/Components/Web/src/Forms/EditForm.cs @@ -28,26 +28,26 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets a collection of additional attributes that will be applied to the created form element. /// - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; private set; } + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; set; } /// /// Supplies the edit context explicitly. If using this parameter, do not /// also supply , since the model value will be taken /// from the property. /// - [Parameter] public EditContext EditContext { get; private set; } + [Parameter] public EditContext EditContext { get; set; } /// /// Specifies the top-level model object for the form. An edit context will /// be constructed for this model. If using this parameter, do not also supply /// a value for . /// - [Parameter] public object Model { get; private set; } + [Parameter] public object Model { get; set; } /// /// Specifies the content to be rendered inside this . /// - [Parameter] public RenderFragment ChildContent { get; private set; } + [Parameter] public RenderFragment ChildContent { get; set; } /// /// A callback that will be invoked when the form is submitted. @@ -55,19 +55,19 @@ namespace Microsoft.AspNetCore.Components.Forms /// If using this parameter, you are responsible for triggering any validation /// manually, e.g., by calling . /// - [Parameter] public EventCallback OnSubmit { get; private set; } + [Parameter] public EventCallback OnSubmit { get; set; } /// /// A callback that will be invoked when the form is submitted and the /// is determined to be valid. /// - [Parameter] public EventCallback OnValidSubmit { get; private set; } + [Parameter] public EventCallback OnValidSubmit { get; set; } /// /// A callback that will be invoked when the form is submitted and the /// is determined to be invalid. /// - [Parameter] public EventCallback OnInvalidSubmit { get; private set; } + [Parameter] public EventCallback OnInvalidSubmit { get; set; } /// protected override void OnParametersSet() @@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Components.Forms builder.OpenComponent>(3); builder.AddAttribute(4, "IsFixed", true); builder.AddAttribute(5, "Value", _fixedEditContext); - builder.AddAttribute(6, RenderTreeBuilder.ChildContent, ChildContent?.Invoke(_fixedEditContext)); + builder.AddAttribute(6, "ChildContent", ChildContent?.Invoke(_fixedEditContext)); builder.CloseComponent(); builder.CloseElement(); diff --git a/src/Components/Components/src/Forms/InputComponents/InputBase.cs b/src/Components/Web/src/Forms/InputBase.cs similarity index 93% rename from src/Components/Components/src/Forms/InputComponents/InputBase.cs rename to src/Components/Web/src/Forms/InputBase.cs index 518876717f..4202aec396 100644 --- a/src/Components/Components/src/Forms/InputComponents/InputBase.cs +++ b/src/Components/Web/src/Forms/InputBase.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets a collection of additional attributes that will be applied to the created element. /// - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; private set; } + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; set; } /// /// Gets or sets the value of the input. This should be used with two-way binding. @@ -32,27 +32,27 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// @bind-Value="model.PropertyName" /// - [Parameter] public T Value { get; private set; } + [Parameter] public T Value { get; set; } /// /// Gets or sets a callback that updates the bound value. /// - [Parameter] public EventCallback ValueChanged { get; private set; } + [Parameter] public EventCallback ValueChanged { get; set; } /// /// Gets or sets an expression that identifies the bound value. /// - [Parameter] public Expression> ValueExpression { get; private set; } + [Parameter] public Expression> ValueExpression { get; set; } /// /// Gets the associated . /// - protected EditContext EditContext { get; private set; } + protected EditContext EditContext { get; set; } /// /// Gets the for the bound value. /// - protected FieldIdentifier FieldIdentifier { get; private set; } + protected FieldIdentifier FieldIdentifier { get; set; } /// /// Gets or sets the current value of the input. @@ -143,8 +143,8 @@ namespace Microsoft.AspNetCore.Components.Forms /// Gets a string that indicates the status of the field being edited. This will include /// some combination of "modified", "valid", or "invalid", depending on the status of the field. /// - protected string FieldClass - => EditContext.FieldClass(FieldIdentifier); + private string FieldClass + => EditContext.FieldCssClass(FieldIdentifier); /// /// Gets a CSS class string that combines the class attribute and @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// - public override Task SetParametersAsync(ParameterCollection parameters) + public override Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); @@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Components.Forms } // For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc. - return base.SetParametersAsync(ParameterCollection.Empty); + return base.SetParametersAsync(ParameterView.Empty); } } } diff --git a/src/Components/Components/src/Forms/InputComponents/InputCheckbox.cs b/src/Components/Web/src/Forms/InputCheckbox.cs similarity index 100% rename from src/Components/Components/src/Forms/InputComponents/InputCheckbox.cs rename to src/Components/Web/src/Forms/InputCheckbox.cs diff --git a/src/Components/Components/src/Forms/InputComponents/InputDate.cs b/src/Components/Web/src/Forms/InputDate.cs similarity index 97% rename from src/Components/Components/src/Forms/InputComponents/InputDate.cs rename to src/Components/Web/src/Forms/InputDate.cs index f080af908d..416fd38587 100644 --- a/src/Components/Components/src/Forms/InputComponents/InputDate.cs +++ b/src/Components/Web/src/Forms/InputDate.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets the error message used when displaying an a parsing error. /// - [Parameter] public string ParsingErrorMessage { get; private set; } = "The {0} field must be a date."; + [Parameter] public string ParsingErrorMessage { get; set; } = "The {0} field must be a date."; /// protected override void BuildRenderTree(RenderTreeBuilder builder) diff --git a/src/Components/Components/src/Forms/InputComponents/InputNumber.cs b/src/Components/Web/src/Forms/InputNumber.cs similarity index 97% rename from src/Components/Components/src/Forms/InputComponents/InputNumber.cs rename to src/Components/Web/src/Forms/InputNumber.cs index c5a222f6ff..a685644c8d 100644 --- a/src/Components/Components/src/Forms/InputComponents/InputNumber.cs +++ b/src/Components/Web/src/Forms/InputNumber.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets the error message used when displaying an a parsing error. /// - [Parameter] public string ParsingErrorMessage { get; private set; } = "The {0} field must be a number."; + [Parameter] public string ParsingErrorMessage { get; set; } = "The {0} field must be a number."; /// protected override void BuildRenderTree(RenderTreeBuilder builder) diff --git a/src/Components/Components/src/Forms/InputComponents/InputSelect.cs b/src/Components/Web/src/Forms/InputSelect.cs similarity index 96% rename from src/Components/Components/src/Forms/InputComponents/InputSelect.cs rename to src/Components/Web/src/Forms/InputSelect.cs index fda1822afe..5b9cb0ca66 100644 --- a/src/Components/Components/src/Forms/InputComponents/InputSelect.cs +++ b/src/Components/Web/src/Forms/InputSelect.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets the child content to be rendering inside the select element. /// - [Parameter] public RenderFragment ChildContent { get; private set; } + [Parameter] public RenderFragment ChildContent { get; set; } /// protected override void BuildRenderTree(RenderTreeBuilder builder) diff --git a/src/Components/Components/src/Forms/InputComponents/InputText.cs b/src/Components/Web/src/Forms/InputText.cs similarity index 100% rename from src/Components/Components/src/Forms/InputComponents/InputText.cs rename to src/Components/Web/src/Forms/InputText.cs diff --git a/src/Components/Components/src/Forms/InputComponents/InputTextArea.cs b/src/Components/Web/src/Forms/InputTextArea.cs similarity index 100% rename from src/Components/Components/src/Forms/InputComponents/InputTextArea.cs rename to src/Components/Web/src/Forms/InputTextArea.cs diff --git a/src/Components/Components/src/Forms/ValidationMessage.cs b/src/Components/Web/src/Forms/ValidationMessage.cs similarity index 93% rename from src/Components/Components/src/Forms/ValidationMessage.cs rename to src/Components/Web/src/Forms/ValidationMessage.cs index ef8ee1fbd8..f4676d7921 100644 --- a/src/Components/Components/src/Forms/ValidationMessage.cs +++ b/src/Components/Web/src/Forms/ValidationMessage.cs @@ -21,14 +21,14 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets a collection of additional attributes that will be applied to the created div element. /// - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; private set; } + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; set; } [CascadingParameter] EditContext CurrentEditContext { get; set; } /// /// Specifies the field for which validation messages should be displayed. /// - [Parameter] public Expression> For { get; private set; } + [Parameter] public Expression> For { get; set; } /// ` /// Constructs an instance of . @@ -85,9 +85,14 @@ namespace Microsoft.AspNetCore.Components.Forms StateHasChanged(); } + protected virtual void Dispose(bool disposing) + { + } + void IDisposable.Dispose() { DetachValidationStateChangedListener(); + Dispose(disposing: true); } private void DetachValidationStateChangedListener() diff --git a/src/Components/Components/src/Forms/ValidationSummary.cs b/src/Components/Web/src/Forms/ValidationSummary.cs similarity index 95% rename from src/Components/Components/src/Forms/ValidationSummary.cs rename to src/Components/Web/src/Forms/ValidationSummary.cs index 1bd46fde66..b0ed6596cd 100644 --- a/src/Components/Components/src/Forms/ValidationSummary.cs +++ b/src/Components/Web/src/Forms/ValidationSummary.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets or sets a collection of additional attributes that will be applied to the created ul element. /// - [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; private set; } + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; set; } [CascadingParameter] EditContext CurrentEditContext { get; set; } @@ -82,9 +82,14 @@ namespace Microsoft.AspNetCore.Components.Forms StateHasChanged(); } + protected virtual void Dispose(bool disposing) + { + } + void IDisposable.Dispose() { DetachValidationStateChangedListener(); + Dispose(disposing: true); } private void DetachValidationStateChangedListener() diff --git a/src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj b/src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj index 7515d745de..59c78672b1 100644 --- a/src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj +++ b/src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj @@ -6,6 +6,7 @@ Support for rendering ASP.NET Core components for browsers. true true + Microsoft.AspNetCore.Components diff --git a/src/Components/Web/src/RendererRegistryEventDispatcher.cs b/src/Components/Web/src/RendererRegistryEventDispatcher.cs index 0a6879a8c2..7bffa1ec6e 100644 --- a/src/Components/Web/src/RendererRegistryEventDispatcher.cs +++ b/src/Components/Web/src/RendererRegistryEventDispatcher.cs @@ -18,8 +18,7 @@ namespace Microsoft.AspNetCore.Components.Web /// For framework use only. /// [JSInvokable(nameof(DispatchEvent))] - public static Task DispatchEvent( - BrowserEventDescriptor eventDescriptor, string eventArgsJson) + public static Task DispatchEvent(BrowserEventDescriptor eventDescriptor, string eventArgsJson) { InterpretEventDescriptor(eventDescriptor); var eventArgs = ParseEventArgsJson(eventDescriptor.EventArgsType, eventArgsJson); @@ -55,12 +54,12 @@ namespace Microsoft.AspNetCore.Components.Web } } - private static UIEventArgs ParseEventArgsJson(string eventArgsType, string eventArgsJson) + private static EventArgs ParseEventArgsJson(string eventArgsType, string eventArgsJson) { switch (eventArgsType) { case "change": - return DeserializeUIEventChangeArgs(eventArgsJson); + return DeserializeChangeEventArgs(eventArgsJson); case "clipboard": return Deserialize(eventArgsJson); case "drag": @@ -80,7 +79,7 @@ namespace Microsoft.AspNetCore.Components.Web case "touch": return Deserialize(eventArgsJson); case "unknown": - return Deserialize(eventArgsJson); + return EventArgs.Empty; case "wheel": return Deserialize(eventArgsJson); default: @@ -93,9 +92,9 @@ namespace Microsoft.AspNetCore.Components.Web return JsonSerializer.Deserialize(eventArgsJson, JsonSerializerOptionsProvider.Options); } - private static UIChangeEventArgs DeserializeUIEventChangeArgs(string eventArgsJson) + private static ChangeEventArgs DeserializeChangeEventArgs(string eventArgsJson) { - var changeArgs = Deserialize(eventArgsJson); + var changeArgs = Deserialize(eventArgsJson); var jsonElement = (JsonElement)changeArgs.Value; switch (jsonElement.ValueKind) { @@ -110,7 +109,7 @@ namespace Microsoft.AspNetCore.Components.Web changeArgs.Value = jsonElement.GetBoolean(); break; default: - throw new ArgumentException($"Unsupported {nameof(UIChangeEventArgs)} value {jsonElement}."); + throw new ArgumentException($"Unsupported {nameof(ChangeEventArgs)} value {jsonElement}."); } return changeArgs; } diff --git a/src/Components/Components/src/Routing/NavLink.cs b/src/Components/Web/src/Routing/NavLink.cs similarity index 92% rename from src/Components/Components/src/Routing/NavLink.cs rename to src/Components/Web/src/Routing/NavLink.cs index 155a973cf1..949904e4d4 100644 --- a/src/Components/Components/src/Routing/NavLink.cs +++ b/src/Components/Web/src/Routing/NavLink.cs @@ -25,19 +25,19 @@ namespace Microsoft.AspNetCore.Components.Routing /// current route matches the NavLink href. /// [Parameter] - public string ActiveClass { get; private set; } + public string ActiveClass { get; set; } /// /// Gets or sets a collection of additional attributes that will be added to the generated /// a element. /// [Parameter(CaptureUnmatchedValues = true)] - public IReadOnlyDictionary AdditionalAttributes { get; private set; } + public IReadOnlyDictionary AdditionalAttributes { get; set; } /// /// Gets or sets the computed CSS class based on whether or not the link is active. /// - protected string CssClass { get; private set; } + protected string CssClass { get; set; } /// /// Gets or sets the child content of the component. @@ -49,15 +49,15 @@ namespace Microsoft.AspNetCore.Components.Routing /// Gets or sets a value representing the URL matching behavior. /// [Parameter] - public NavLinkMatch Match { get; private set; } + public NavLinkMatch Match { get; set; } - [Inject] private IUriHelper UriHelper { get; set; } + [Inject] private NavigationManager NavigationManger { get; set; } /// protected override void OnInitialized() { // We'll consider re-rendering on each location change - UriHelper.OnLocationChanged += OnLocationChanged; + NavigationManger.LocationChanged += OnLocationChanged; } /// @@ -70,8 +70,8 @@ namespace Microsoft.AspNetCore.Components.Routing href = Convert.ToString(obj); } - _hrefAbsolute = href == null ? null : UriHelper.ToAbsoluteUri(href).AbsoluteUri; - _isActive = ShouldMatch(UriHelper.GetAbsoluteUri()); + _hrefAbsolute = href == null ? null : NavigationManger.ToAbsoluteUri(href).AbsoluteUri; + _isActive = ShouldMatch(NavigationManger.Uri); _class = (string)null; if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("class", out obj)) @@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Components.Routing public void Dispose() { // To avoid leaking memory, it's important to detach any event handlers in Dispose() - UriHelper.OnLocationChanged -= OnLocationChanged; + NavigationManger.LocationChanged -= OnLocationChanged; } private void UpdateCssClass() diff --git a/src/Components/Components/src/Routing/NavLinkMatch.cs b/src/Components/Web/src/Routing/NavLinkMatch.cs similarity index 100% rename from src/Components/Components/src/Routing/NavLinkMatch.cs rename to src/Components/Web/src/Routing/NavLinkMatch.cs diff --git a/src/Components/Web/src/UIClipboardEventArgs.cs b/src/Components/Web/src/UIClipboardEventArgs.cs new file mode 100644 index 0000000000..166d9221c1 --- /dev/null +++ b/src/Components/Web/src/UIClipboardEventArgs.cs @@ -0,0 +1,18 @@ +// Copyright (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 clipboard event that is being raised. + /// + public class UIClipboardEventArgs : EventArgs + { + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIDataTransferItem.cs b/src/Components/Web/src/UIDataTransferItem.cs new file mode 100644 index 0000000000..1adc32dcf7 --- /dev/null +++ b/src/Components/Web/src/UIDataTransferItem.cs @@ -0,0 +1,23 @@ +// Copyright (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 +{ + /// + /// The object represents one drag data item. + /// During a drag operation, each drag event has a dataTransfer property which contains a list of drag data items. + /// Each item in the list is a object. + /// + public class UIDataTransferItem + { + /// + /// The kind of drag data item, string or file + /// + public string Kind { get; set; } + + /// + /// The drag data item's type, typically a MIME type + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIDragEventArgs.cs b/src/Components/Web/src/UIDragEventArgs.cs new file mode 100644 index 0000000000..483b1827e3 --- /dev/null +++ b/src/Components/Web/src/UIDragEventArgs.cs @@ -0,0 +1,17 @@ +// Copyright (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 +{ + /// + /// Supplies information about an drag event that is being raised. + /// + public class UIDragEventArgs : UIMouseEventArgs + { + /// + /// The data that underlies a drag-and-drop operation, known as the drag data store. + /// See . + /// + public DataTransfer DataTransfer { get; set; } + } +} diff --git a/src/Components/Web/src/UIErrorEventArgs.cs b/src/Components/Web/src/UIErrorEventArgs.cs new file mode 100644 index 0000000000..6cf86b7553 --- /dev/null +++ b/src/Components/Web/src/UIErrorEventArgs.cs @@ -0,0 +1,38 @@ +// Copyright (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 error event that is being raised. + /// + public class UIErrorEventArgs : EventArgs + { + /// + /// Gets a a human-readable error message describing the problem. + /// + public string Message { get; set; } + + /// + /// Gets the name of the script file in which the error occurred. + /// + public string Filename { get; set; } + + /// + /// Gets the line number of the script file on which the error occurred. + /// + public int Lineno { get; set; } + + /// + /// Gets the column number of the script file on which the error occurred. + /// + public int Colno { get; set; } + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIFocusEventArgs.cs b/src/Components/Web/src/UIFocusEventArgs.cs new file mode 100644 index 0000000000..b120e666a8 --- /dev/null +++ b/src/Components/Web/src/UIFocusEventArgs.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 System; + +namespace Microsoft.AspNetCore.Components +{ + /// + /// Supplies information about a focus event that is being raised. + /// + public class UIFocusEventArgs : EventArgs + { + // Not including support for 'relatedTarget' since we don't have a good way to represent it. + // see: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIKeyboardEventArgs.cs b/src/Components/Web/src/UIKeyboardEventArgs.cs new file mode 100644 index 0000000000..fd66247dc4 --- /dev/null +++ b/src/Components/Web/src/UIKeyboardEventArgs.cs @@ -0,0 +1,62 @@ +// Copyright (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 a keyboard event that is being raised. + /// + public class UIKeyboardEventArgs : EventArgs + { + /// + /// The key value of the key represented by the event. + /// If the value has a printed representation, this attribute's value is the same as the char attribute. + /// Otherwise, it's one of the key value strings specified in 'Key values'. + /// If the key can't be identified, this is the string "Unidentified" + /// + public string Key { get; set; } + + /// + /// Holds a string that identifies the physical key being pressed. + /// The value is not affected by the current keyboard layout or modifier state, so a particular key will always return the same value. + /// + public string Code { get; set; } + + /// + /// The location of the key on the device. + /// + public float Location { get; set; } + + /// + /// true if a key has been depressed long enough to trigger key repetition, otherwise false. + /// + public bool Repeat { get; set; } + + /// + /// true if the control key was down when the event was fired. false otherwise. + /// + public bool CtrlKey { get; set; } + + /// + /// true if the shift key was down when the event was fired. false otherwise. + /// + public bool ShiftKey { get; set; } + + /// + /// true if the alt key was down when the event was fired. false otherwise. + /// + public bool AltKey { get; set; } + + /// + /// true if the meta key was down when the event was fired. false otherwise. + /// + public bool MetaKey { get; set; } + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIMouseEventArgs.cs b/src/Components/Web/src/UIMouseEventArgs.cs new file mode 100644 index 0000000000..da4d2a64ae --- /dev/null +++ b/src/Components/Web/src/UIMouseEventArgs.cs @@ -0,0 +1,84 @@ +// Copyright (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 a mouse event that is being raised. + /// + public class UIMouseEventArgs : EventArgs + { + /// + /// A count of consecutive clicks that happened in a short amount of time, incremented by one. + /// + public long Detail { get; set; } + + /// + /// The X coordinate of the mouse pointer in global (screen) coordinates. + /// + public double ScreenX { get; set; } + + /// + /// The Y coordinate of the mouse pointer in global (screen) coordinates. + /// + public double ScreenY { get; set; } + + /// + /// The X coordinate of the mouse pointer in local (DOM content) coordinates. + /// + public double ClientX { get; set; } + + /// + /// The Y coordinate of the mouse pointer in local (DOM content) coordinates. + /// + public double ClientY { get; set; } + + /// + /// The button number that was pressed when the mouse event was fired: + /// Left button=0, + /// middle button=1 (if present), + /// right button=2. + /// For mice configured for left handed use in which the button actions are reversed the values are instead read from right to left. + /// + public long Button { get; set; } + + /// + /// The buttons being pressed when the mouse event was fired: + /// Left button=1, + /// Right button=2, + /// Middle (wheel) button=4, + /// 4th button (typically, "Browser Back" button)=8, + /// 5th button (typically, "Browser Forward" button)=16. + /// If two or more buttons are pressed, returns the logical sum of the values. + /// E.g., if Left button and Right button are pressed, returns 3 (=1 | 2). + /// + public long Buttons { get; set; } + + /// + /// true if the control key was down when the event was fired. false otherwise. + /// + public bool CtrlKey { get; set; } + + /// + /// true if the shift key was down when the event was fired. false otherwise. + /// + public bool ShiftKey { get; set; } + + /// + /// true if the alt key was down when the event was fired. false otherwise. + /// + public bool AltKey { get; set; } + + /// + /// true if the meta key was down when the event was fired. false otherwise. + /// + public bool MetaKey { get; set; } + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UIPointerEventArgs.cs b/src/Components/Web/src/UIPointerEventArgs.cs new file mode 100644 index 0000000000..348cfbefd5 --- /dev/null +++ b/src/Components/Web/src/UIPointerEventArgs.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. + +namespace Microsoft.AspNetCore.Components +{ + /// + /// Supplies information about a pointer event that is being raised. + /// + public class UIPointerEventArgs : UIMouseEventArgs + { + /// + /// A unique identifier for the pointer causing the event. + /// + public long PointerId { get; set; } + + /// + /// The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer. + /// + public float Width { get; set; } + + /// + /// The height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer. + /// + public float Height { get; set; } + + /// + /// The normalized pressure of the pointer input in the range of 0 to 1, + /// where 0 and 1 represent the minimum and maximum pressure the hardware is capable of detecting, respectively. + /// + public float Pressure { get; set; } + + /// + /// The plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane + /// and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis. + /// + public float TiltX { get; set; } + + /// + /// The plane angle (in degrees, in the range of -90 to 90) between the X-Z plane + /// and the plane containing both the transducer (e.g. pen stylus) axis and the X axis. + /// + public float TiltY { get; set; } + + /// + /// Indicates the device type that caused the event. + /// Must be one of the strings mouse, pen or touch, or an empty string. + /// + public string PointerType { get; set; } + + /// + /// Indicates if the pointer represents the primary pointer of this pointer type. + /// + public bool IsPrimary { get; set; } + } +} diff --git a/src/Components/Web/src/UIProgressEventArgs.cs b/src/Components/Web/src/UIProgressEventArgs.cs new file mode 100644 index 0000000000..e0273c665f --- /dev/null +++ b/src/Components/Web/src/UIProgressEventArgs.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; + +namespace Microsoft.AspNetCore.Components +{ + /// + /// Supplies information about a progress event that is being raised. + /// + public class UIProgressEventArgs : EventArgs + { + /// + /// Whether or not the total size of the transfer is known. + /// + public bool LengthComputable { get; set; } + + /// + /// The number of bytes transferred since the beginning of the operation. + /// This doesn't include headers and other overhead, but only the content itself. + /// + public long Loaded { get; set; } + + /// + /// The total number of bytes of content that will be transferred during the operation. + /// If the total size is unknown, this value is zero. + /// + public long Total { get; set; } + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UITouchEventArgs.cs b/src/Components/Web/src/UITouchEventArgs.cs new file mode 100644 index 0000000000..3be004b7f1 --- /dev/null +++ b/src/Components/Web/src/UITouchEventArgs.cs @@ -0,0 +1,61 @@ +// Copyright (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 a touch event that is being raised. + /// + public class UITouchEventArgs : EventArgs + { + /// + /// A count of consecutive clicks that happened in a short amount of time, incremented by one. + /// + public long Detail { get; set; } + + /// + /// A list of for every point of contact currently touching the surface. + /// + public UITouchPoint[] Touches { get; set; } + + /// + /// A list of for every point of contact that is touching the surface and started on the element that is the target of the current event. + /// + public UITouchPoint[] TargetTouches { get; set; } + + /// + /// A list of Touches for every point of contact which contributed to the event. + /// For the touchstart event this must be a list of the touch points that just became active with the current event. + /// For the touchmove event this must be a list of the touch points that have moved since the last event. + /// For the touchend and touchcancel events this must be a list of the touch points that have just been removed from the surface. + /// + public UITouchPoint[] ChangedTouches { get; set; } + + /// + /// true if the control key was down when the event was fired. false otherwise. + /// + public bool CtrlKey { get; set; } + + /// + /// true if the shift key was down when the event was fired. false otherwise. + /// + public bool ShiftKey { get; set; } + + /// + /// true if the alt key was down when the event was fired. false otherwise. + /// + public bool AltKey { get; set; } + + /// + /// true if the meta key was down when the event was fired. false otherwise. + /// + public bool MetaKey { get; set; } + + /// + /// Gets or sets the type of the event. + /// + public string Type { get; set; } + } +} diff --git a/src/Components/Web/src/UITouchPoint.cs b/src/Components/Web/src/UITouchPoint.cs new file mode 100644 index 0000000000..9fe154f118 --- /dev/null +++ b/src/Components/Web/src/UITouchPoint.cs @@ -0,0 +1,51 @@ +// Copyright (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 contact point on a touch-sensitive device. + /// The contact point is commonly a finger or stylus and the device may be a touchscreen or trackpad. + /// + public class UITouchPoint + { + /// + /// A unique identifier for this Touch object. + /// A given touch point (say, by a finger) will have the same identifier for the duration of its movement around the surface. + /// This lets you ensure that you're tracking the same touch all the time. + /// + public long Identifier { get; set; } + + /// + /// The X coordinate of the touch point relative to the left edge of the screen. + /// + public double ScreenX { get; set; } + + /// + /// The Y coordinate of the touch point relative to the top edge of the screen. + /// + public double ScreenY { get; set; } + + /// + /// The X coordinate of the touch point relative to the left edge of the browser viewport, not including any scroll offset. + /// + public double ClientX { get; set; } + + /// + /// The Y coordinate of the touch point relative to the top edge of the browser viewport, not including any scroll offset. + /// + public double ClientY { get; set; } + + /// + /// The X coordinate of the touch point relative to the left edge of the document. + /// Unlike , this value includes the horizontal scroll offset, if any. + /// + public double PageX { get; set; } + + /// + /// The Y coordinate of the touch point relative to the top of the document. + /// Unlike , this value includes the vertical scroll offset, if any. + /// + public double PageY { get; set; } + } +} diff --git a/src/Components/Web/src/UIWheelEventArgs.cs b/src/Components/Web/src/UIWheelEventArgs.cs new file mode 100644 index 0000000000..b73baa96f9 --- /dev/null +++ b/src/Components/Web/src/UIWheelEventArgs.cs @@ -0,0 +1,31 @@ +// Copyright (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 +{ + /// + /// Supplies information about a mouse wheel event that is being raised. + /// + public class UIWheelEventArgs : UIMouseEventArgs + { + /// + /// The horizontal scroll amount. + /// + public double DeltaX { get; set; } + + /// + /// The vertical scroll amount. + /// + public double DeltaY { get; set; } + + /// + /// The scroll amount for the z-axis. + /// + public double DeltaZ { get; set; } + + /// + /// The unit of the delta values scroll amount. + /// + public long DeltaMode { get; set; } + } +} diff --git a/src/Components/Components/src/EventCallbackFactoryUIEventArgsExtensions.cs b/src/Components/Web/src/WebEventCallbackFactoryUIEventArgsExtensions.cs similarity index 83% rename from src/Components/Components/src/EventCallbackFactoryUIEventArgsExtensions.cs rename to src/Components/Web/src/WebEventCallbackFactoryUIEventArgsExtensions.cs index 0e8151d56a..02bb5d6d58 100644 --- a/src/Components/Components/src/EventCallbackFactoryUIEventArgsExtensions.cs +++ b/src/Components/Web/src/WebEventCallbackFactoryUIEventArgsExtensions.cs @@ -7,83 +7,10 @@ using System.Threading.Tasks; namespace Microsoft.AspNetCore.Components { /// - /// Provides extension methods for and types. For internal - /// framework use. + /// Provides extension methods for and types. /// - public static class EventCallbackFactoryUIEventArgsExtensions + public static class WebEventCallbackFactoryUIEventArgsExtensions { - /// - /// 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); - } - /// /// Creates an for the provided and /// . diff --git a/src/Components/Components/test/Forms/InputBaseTest.cs b/src/Components/Web/test/Forms/InputBaseTest.cs similarity index 96% rename from src/Components/Components/test/Forms/InputBaseTest.cs rename to src/Components/Web/test/Forms/InputBaseTest.cs index 62e40cb88b..8be8525365 100644 --- a/src/Components/Components/test/Forms/InputBaseTest.cs +++ b/src/Components/Web/test/Forms/InputBaseTest.cs @@ -213,28 +213,23 @@ namespace Microsoft.AspNetCore.Components.Forms // Act/Assert: Initally, it's valid and unmodified var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); - Assert.Equal("valid", inputComponent.FieldClass); - Assert.Equal("valid", inputComponent.CssClass); // Same because no Class was specified + Assert.Equal("valid", inputComponent.CssClass); // no Class was specified // Act/Assert: Modify the field rootComponent.EditContext.NotifyFieldChanged(fieldIdentifier); - Assert.Equal("modified valid", inputComponent.FieldClass); Assert.Equal("modified valid", inputComponent.CssClass); // Act/Assert: Make it invalid var messages = new ValidationMessageStore(rootComponent.EditContext); messages.Add(fieldIdentifier, "I do not like this value"); - Assert.Equal("modified invalid", inputComponent.FieldClass); Assert.Equal("modified invalid", inputComponent.CssClass); // Act/Assert: Clear the modification flag rootComponent.EditContext.MarkAsUnmodified(fieldIdentifier); - Assert.Equal("invalid", inputComponent.FieldClass); Assert.Equal("invalid", inputComponent.CssClass); // Act/Assert: Make it valid messages.Clear(); - Assert.Equal("valid", inputComponent.FieldClass); Assert.Equal("valid", inputComponent.CssClass); } @@ -256,12 +251,10 @@ namespace Microsoft.AspNetCore.Components.Forms // Act/Assert var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); - Assert.Equal("valid", inputComponent.FieldClass); Assert.Equal("my-class other-class valid", inputComponent.CssClass); // Act/Assert: Retains custom class when changing field class rootComponent.EditContext.NotifyFieldChanged(fieldIdentifier); - Assert.Equal("modified valid", inputComponent.FieldClass); Assert.Equal("my-class other-class modified valid", inputComponent.CssClass); } @@ -393,8 +386,6 @@ namespace Microsoft.AspNetCore.Components.Forms public new FieldIdentifier FieldIdentifier => base.FieldIdentifier; - public new string FieldClass => base.FieldClass; - protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) { throw new NotImplementedException(); @@ -437,7 +428,7 @@ namespace Microsoft.AspNetCore.Components.Forms { builder.OpenComponent>(0); builder.AddAttribute(1, "Value", EditContext); - builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder => + builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent(0); childBuilder.AddAttribute(0, "Value", Value); diff --git a/src/Components/Web/test/Microsoft.AspNetCore.Components.Web.Tests.csproj b/src/Components/Web/test/Microsoft.AspNetCore.Components.Web.Tests.csproj new file mode 100644 index 0000000000..ae732d3e10 --- /dev/null +++ b/src/Components/Web/test/Microsoft.AspNetCore.Components.Web.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp3.0 + Microsoft.AspNetCore.Components + + + + + + + + + + + + + + diff --git a/src/Components/test/E2ETest/Infrastructure/BasicTestAppTestBase.cs b/src/Components/test/E2ETest/Infrastructure/BasicTestAppTestBase.cs index 62d62f0d68..e9539fc9f9 100644 --- a/src/Components/test/E2ETest/Infrastructure/BasicTestAppTestBase.cs +++ b/src/Components/test/E2ETest/Infrastructure/BasicTestAppTestBase.cs @@ -1,13 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Linq; using BasicTestApp; -using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; -using System; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure @@ -38,16 +37,35 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure protected SelectElement WaitUntilTestSelectorReady() { var elemToFind = By.CssSelector("#test-selector > select"); - WaitUntilExists(elemToFind, timeoutSeconds: 30); + WaitUntilExists(elemToFind, timeoutSeconds: 30, throwOnError: true); return new SelectElement(Browser.FindElement(elemToFind)); } - protected IWebElement WaitUntilExists(By findBy, int timeoutSeconds = 10) + protected void SignInAs(string usernameOrNull, string rolesOrNull, bool useSeparateTab = false) { - IWebElement result = null; - new WebDriverWait(Browser, TimeSpan.FromSeconds(timeoutSeconds)) - .Until(driver => (result = driver.FindElement(findBy)) != null); - return result; + const string authenticationPageUrl = "/Authentication"; + var baseRelativeUri = usernameOrNull == null + ? $"{authenticationPageUrl}?signout=true" + : $"{authenticationPageUrl}?username={usernameOrNull}&roles={rolesOrNull}"; + + if (useSeparateTab) + { + // Some tests need to change the authentication state without discarding the + // original page, but this adds several seconds of delay + var javascript = (IJavaScriptExecutor)Browser; + var originalWindow = Browser.CurrentWindowHandle; + javascript.ExecuteScript("window.open()"); + Browser.SwitchTo().Window(Browser.WindowHandles.Last()); + Navigate(baseRelativeUri); + WaitUntilExists(By.CssSelector("h1#authentication")); + javascript.ExecuteScript("window.close()"); + Browser.SwitchTo().Window(originalWindow); + } + else + { + Navigate(baseRelativeUri); + WaitUntilExists(By.CssSelector("h1#authentication")); + } } } } diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs index 3cd8539c61..742a83f12f 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.ExceptionServices; using System.Threading; namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures @@ -52,13 +53,30 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures { var isDone = new ManualResetEvent(false); + ExceptionDispatchInfo edi = null; new Thread(() => { - action(); + try + { + action(); + } + catch (Exception ex) + { + edi = ExceptionDispatchInfo.Capture(ex); + } + isDone.Set(); }).Start(); - isDone.WaitOne(); + if (!isDone.WaitOne(TimeSpan.FromSeconds(10))) + { + throw new TimeoutException("Timed out waiting for: " + action); + } + + if (edi != null) + { + throw edi.SourceException; + } } } } diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs index 56be3c9256..cda7c50420 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Hosting; namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures { @@ -11,6 +12,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures { public string PathBase { get; set; } + public IWebHost Host { get; set; } + public ExecutionMode ExecutionMode { get; set; } = ExecutionMode.Client; private AspNetSiteServerFixture.BuildWebHost _buildWebHostMethod; @@ -32,7 +35,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures var underlying = new DevHostServerFixture(); underlying.PathBase = PathBase; _serverToDispose = underlying; - return underlying.RootUri.AbsoluteUri; + var uri = underlying.RootUri.AbsoluteUri; // As a side-effect, this starts the server + + Host = underlying.Host; + + return uri; } else { @@ -41,7 +48,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures underlying.AdditionalArguments.AddRange(AspNetFixtureAdditionalArguments); underlying.BuildWebHostMethod = _buildWebHostMethod; _serverToDispose = underlying; - return underlying.RootUri.AbsoluteUri; + var uri = underlying.RootUri.AbsoluteUri; // As a side-effect, this starts the server + + Host = underlying.Host; + + return uri; } } diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/WebHostServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/WebHostServerFixture.cs index 2ff15cbe62..1da2656b37 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/WebHostServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/WebHostServerFixture.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Hosting; @@ -9,22 +9,23 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures { public abstract class WebHostServerFixture : ServerFixture { - private IWebHost _host; - protected override string StartAndGetRootUri() { - _host = CreateWebHost(); - RunInBackgroundThread(_host.Start); - return _host.ServerFeatures + Host = CreateWebHost(); + RunInBackgroundThread(Host.Start); + return Host.ServerFeatures .Get() .Addresses.Single(); } + public IWebHost Host { get; set; } + public override void Dispose() { // This can be null if creating the webhost throws, we don't want to throw here and hide // the original exception. - _host?.StopAsync(); + Host?.Dispose(); + Host?.StopAsync(); } protected abstract IWebHost CreateWebHost(); diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj index 9e85027c89..fc3a9c6dfa 100644 --- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj +++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj @@ -7,12 +7,16 @@ netcoreapp3.0 Components.E2ETests - true false + + + true + + diff --git a/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs b/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs new file mode 100644 index 0000000000..f383818386 --- /dev/null +++ b/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs @@ -0,0 +1,111 @@ +// Copyright (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 BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Testing; +using OpenQA.Selenium; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests +{ + public class CircuitGracefulTerminationTests : BasicTestAppTestBase, IDisposable + { + public CircuitGracefulTerminationTests( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture.WithServerExecution(), output) + { + } + + public TaskCompletionSource GracefulDisconnectCompletionSource { get; private set; } + public TestSink Sink { get; private set; } + public List<(Extensions.Logging.LogLevel level, string eventIdName)> Messages { get; private set; } + + public override async Task InitializeAsync() + { + // These tests manipulate the browser in ways that make it impossible to use the same browser + // instance across tests (One of the tests closes the browser). For that reason we simply create + // a new browser instance for every test in this class sos that there are no issues when running + // them together. + await base.InitializeAsync(Guid.NewGuid().ToString()); + } + + protected override void InitializeAsyncCore() + { + Navigate(ServerPathBase, noReload: false); + MountTestComponent(); + Browser.Equal("Current count: 0", () => Browser.FindElement(By.TagName("p")).Text); + + GracefulDisconnectCompletionSource = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); + Sink = _serverFixture.Host.Services.GetRequiredService(); + Messages = new List<(Extensions.Logging.LogLevel level, string eventIdName)>(); + Sink.MessageLogged += Log; + } + + [Fact] + public async Task ReloadingThePage_GracefullyDisconnects_TheCurrentCircuit() + { + // Arrange & Act + _ = ((IJavaScriptExecutor)Browser).ExecuteScript("location.reload()"); + await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); + + // Assert + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + } + + [Fact] + public async Task ClosingTheBrowserWindow_GracefullyDisconnects_TheCurrentCircuit() + { + // Arrange & Act + Browser.Close(); + // Set to null so that other tests in this class can create a new browser if necessary so + // that tests don't fail when running together. + Browser = null; + + await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); + + // Assert + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + } + + [Fact] + public async Task ClosingTheBrowserWindow_GracefullyDisconnects_WhenNavigatingAwayFromThePage() + { + // Arrange & Act + Browser.Navigate().GoToUrl("about:blank"); + await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); + + // Assert + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + } + + private void Log(WriteContext wc) + { + if ((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully") == (wc.LogLevel, wc.EventId.Name)) + { + GracefulDisconnectCompletionSource.TrySetResult(null); + } + Messages.Add((wc.LogLevel, wc.EventId.Name)); + } + + public void Dispose() + { + if (Sink != null) + { + Sink.MessageLogged -= Log; + } + } + } +} diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ComponentHubReliabilityTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ComponentHubReliabilityTest.cs new file mode 100644 index 0000000000..deb353dd9c --- /dev/null +++ b/src/Components/test/E2ETest/ServerExecutionTests/ComponentHubReliabilityTest.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.Threading.Tasks; +using Ignitor; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests +{ + public class ComponentHubReliabilityTest : IClassFixture, IDisposable + { + private static readonly TimeSpan DefaultLatencyTimeout = TimeSpan.FromMilliseconds(500); + private readonly AspNetSiteServerFixture _serverFixture; + + public ComponentHubReliabilityTest(AspNetSiteServerFixture serverFixture) + { + serverFixture.BuildWebHostMethod = TestServer.Program.BuildWebHost; + _serverFixture = serverFixture; + CreateDefaultConfiguration(); + } + + public BlazorClient Client { get; set; } + + private IList Batches { get; set; } = new List(); + private IList Errors { get; set; } = new List(); + private IList Logs { get; set; } = new List(); + + public TestSink TestSink { get; set; } + + private void CreateDefaultConfiguration() + { + Client = new BlazorClient() { DefaultLatencyTimeout = DefaultLatencyTimeout }; + Client.RenderBatchReceived += (id, rendererId, data) => Batches.Add(new Batch(id, rendererId, data)); + Client.OnCircuitError += (error) => Errors.Add(error); + + _ = _serverFixture.RootUri; // this is needed for the side-effects of getting the URI. + TestSink = _serverFixture.Host.Services.GetRequiredService(); + TestSink.MessageLogged += LogMessages; + } + + private void LogMessages(WriteContext context) => Logs.Add(new LogMessage(context.LogLevel, context.Message, context.Exception)); + + [Fact] + public async Task CannotStartMultipleCircuits() + { + // Arrange + var expectedError = "The circuit host '.*?' has already been initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false), "Couldn't connect to the app"); + Assert.Single(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "StartCircuit", + baseUri, + baseUri + "/home")); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Matches(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + } + + [Fact] + public async Task CannotStartCircuitWithNullData() + { + // Arrange + var expectedError = "The uris provided are invalid."; + var rootUri = _serverFixture.RootUri; + var uri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app"); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", null, null)); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Matches(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + } + + [Fact] + public async Task CannotStartCircuitWithInvalidUris() + { + // Arrange + var expectedError = "The uris provided are invalid."; + var rootUri = _serverFixture.RootUri; + var uri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app"); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", uri.AbsoluteUri, "/foo")); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Matches(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + } + + // This is a hand-chosen example of something that will cause an exception in creating the circuit host. + // We want to test this case so that we know what happens when creating the circuit host blows up. + [Fact] + public async Task StartCircuitCausesInitializationError() + { + // Arrange + var expectedError = "The circuit failed to initialize."; + var rootUri = _serverFixture.RootUri; + var uri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app"); + + // Act + // + // These are valid URIs by the BaseUri doesn't contain the Uri - so it fails to initialize. + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", uri, "http://example.com"), TimeSpan.FromHours(1)); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Matches(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + } + + [Fact] + public async Task CannotInvokeJSInteropBeforeInitialization() + { + // Arrange + var expectedError = "Circuit not initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false)); + Assert.Empty(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "BeginInvokeDotNetFromJS", + "", + "", + "", + 0, + "")); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Equal(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'BeginInvokeDotNetFromJS' received before the circuit host initialization")); + } + + [Fact] + public async Task CannotInvokeJSInteropCallbackCompletionsBeforeInitialization() + { + // Arrange + var expectedError = "Circuit not initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false)); + Assert.Empty(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "EndInvokeJSFromDotNet", + 3, + true, + "[]")); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Equal(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'EndInvokeJSFromDotNet' received before the circuit host initialization")); + } + + [Fact] + public async Task CannotDispatchBrowserEventsBeforeInitialization() + { + // Arrange + var expectedError = "Circuit not initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false)); + Assert.Empty(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "DispatchBrowserEvent", + "", + "")); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Equal(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'DispatchBrowserEvent' received before the circuit host initialization")); + } + + [Fact] + public async Task CannotInvokeOnRenderCompletedInitialization() + { + // Arrange + var expectedError = "Circuit not initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false)); + Assert.Empty(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "OnRenderCompleted", + 5, + null)); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Equal(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'OnRenderCompleted' received before the circuit host initialization")); + } + + [Fact] + public async Task CannotInvokeOnLocationChangedBeforeInitialization() + { + // Arrange + var expectedError = "Circuit not initialized."; + var rootUri = _serverFixture.RootUri; + var baseUri = new Uri(rootUri, "/subdir"); + Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false)); + Assert.Empty(Batches); + + // Act + await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync( + "OnLocationChanged", + baseUri.AbsoluteUri, + false)); + + // Assert + var actualError = Assert.Single(Errors); + Assert.Equal(expectedError, actualError); + Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information); + Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'OnLocationChanged' received before the circuit host initialization")); + } + + public void Dispose() + { + TestSink.MessageLogged -= LogMessages; + } + + private class LogMessage + { + public LogMessage(LogLevel logLevel, string message, Exception exception) + { + LogLevel = logLevel; + Message = message; + Exception = exception; + } + + public LogLevel LogLevel { get; set; } + public string Message { get; set; } + public Exception Exception { get; set; } + } + + private class Batch + { + public Batch(int id, int rendererId, byte [] data) + { + Id = id; + RendererId = rendererId; + Data = data; + } + + public int Id { get; } + public int RendererId { get; } + public byte[] Data { get; } + } + } +} diff --git a/src/Components/test/E2ETest/ServerExecutionTests/InteropReliabilityTests.cs b/src/Components/test/E2ETest/ServerExecutionTests/InteropReliabilityTests.cs index 73e7a1f8b2..8b46ee7e0a 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/InteropReliabilityTests.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/InteropReliabilityTests.cs @@ -8,6 +8,11 @@ using System.Text.Json; using System.Threading.Tasks; using Ignitor; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Xunit; namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests @@ -31,9 +36,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027WriteAllText\\u0027 on assembly \\u0027System.IO.FileSystem\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027WriteAllText\\u0027 on assembly \\u0027System.IO.FileSystem\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -45,7 +49,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new[] { ".\\log.txt", "log" })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -56,9 +60,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027MadeUpMethod\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027MadeUpMethod\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -70,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new[] { ".\\log.txt", "log" })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -80,9 +83,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -94,7 +96,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new[] { _serverFixture.RootUri })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -105,9 +107,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -119,7 +120,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new object[] { _serverFixture.RootUri + "counter", false })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -130,9 +131,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new object[] { _serverFixture.RootUri + "counter", false })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -156,8 +156,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests var expectedDotNetObjectRef = "[\"1\",true,{\"__dotNetObject\":1}]"; var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027Reverse\\u0027 on assembly \\u0027\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; - var (interopCalls, batches) = ConfigureClient(); + "\"There was an exception invoking \\u0027Reverse\\u0027 on assembly \\u0027\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests null, JsonSerializer.Serialize(Array.Empty())); - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedDotNetObjectRef)); + Assert.Single(dotNetCompletions, expectedDotNetObjectRef); await Client.InvokeDotNetMethod( "1", @@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(Array.Empty())); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", "[\"1\",true,\"tnatropmI\"]")); + Assert.Single(dotNetCompletions, "[\"1\",true,\"tnatropmI\"]"); await Client.InvokeDotNetMethod( "1", @@ -186,8 +186,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests "Reverse", 3, // non existing ref JsonSerializer.Serialize(Array.Empty())); - - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -199,9 +199,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests var expectedImportantDotNetObjectRef = "[\"1\",true,{\"__dotNetObject\":1}]"; var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027ReceiveTrivial\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; + "\"There was an exception invoking \\u0027ReceiveTrivial\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; - var (interopCalls, batches) = ConfigureClient(); + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); await Client.InvokeDotNetMethod( @@ -211,7 +211,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests null, JsonSerializer.Serialize(Array.Empty())); - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedImportantDotNetObjectRef)); + Assert.Single(dotNetCompletions, expectedImportantDotNetObjectRef); // Act await Client.InvokeDotNetMethod( @@ -222,7 +222,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests JsonSerializer.Serialize(new object[] { new { __dotNetObject = 1 } })); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -233,37 +233,100 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "An exception occurred executing JS interop: The JSON value could not be converted to System.Int32. Path: $ | LineNumber: 0 | BytePositionInLine: 3.. See InnerException for more details."; - var (interopCalls, batches) = ConfigureClient(); + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act - await Client.ClickAsync("triggerjsinterop"); + await Client.ClickAsync("triggerjsinterop-malformed"); - Assert.Single(interopCalls, (4, "sendMalformedCallbackReturn", (string)null)); + var call = interopCalls.FirstOrDefault(call => call.identifier == "sendMalformedCallbackReturn"); + Assert.NotEqual(default, call); - await Client.InvokeDotNetMethod( - 0, - "Microsoft.JSInterop", - "DotNetDispatcher.EndInvoke", - null, - "[4, true, \"{\"]"); + var id = call.id; + await Client.HubConnection.InvokeAsync( + "EndInvokeJSFromDotNet", + id, + true, + $"[{id}, true, \"{{\"]"); var text = Assert.Single( - Client.FindElementById("errormessage").Children.OfType(), + Client.FindElementById("errormessage-malformed").Children.OfType(), e => expectedError == e.TextContent); await ValidateClientKeepsWorking(Client, batches); } + [Fact] + public async Task LogsJSInteropCompletionsCallbacksAndContinuesWorkingInAllSituations() + { + // Arrange + + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name)); + + // Act + await Client.ClickAsync("triggerjsinterop-malformed"); + + var call = interopCalls.FirstOrDefault(call => call.identifier == "sendMalformedCallbackReturn"); + Assert.NotEqual(default, call); + + var id = call.id; + await Client.HubConnection.InvokeAsync( + "EndInvokeJSFromDotNet", + id, + true, + $"[{id}, true, }}"); + + // A completely malformed payload like the one above never gets to the application. + Assert.Single( + Client.FindElementById("errormessage-malformed").Children.OfType(), + e => "" == e.TextContent); + + Assert.Contains((LogLevel.Debug, "EndInvokeDispatchException"), logEvents); + + await Client.ClickAsync("triggerjsinterop-success"); + await Client.HubConnection.InvokeAsync( + "EndInvokeJSFromDotNet", + id++, + true, + $"[{id}, true, null]"); + + Assert.Single( + Client.FindElementById("errormessage-success").Children.OfType(), + e => "" == e.TextContent); + + Assert.Contains((LogLevel.Debug, "EndInvokeJSSucceeded"), logEvents); + + await Client.ClickAsync("triggerjsinterop-failure"); + await Client.HubConnection.InvokeAsync( + "EndInvokeJSFromDotNet", + id++, + false, + $"[{id}, false, \"There was an error invoking sendFailureCallbackReturn\"]"); + + Assert.Single( + Client.FindElementById("errormessage-failure").Children.OfType(), + e => "There was an error invoking sendFailureCallbackReturn" == e.TextContent); + + Assert.Contains((LogLevel.Debug, "EndInvokeJSFailed"), logEvents); + + Assert.DoesNotContain(logEvents, m => m.logLevel > LogLevel.Information); + + await ValidateClientKeepsWorking(Client, batches); + } + [Fact] public async Task CannotInvokeJSInvokableMethodsWithInvalidArgumentsPayload() { // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; + "\"There was an exception invoking \\u0027NotifyLocationChanged\\u0027 on assembly \\u0027Microsoft.AspNetCore.Components.Server\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; - var (interopCalls, batches) = ConfigureClient(); + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -275,7 +338,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests "[ \"invalidPayload\"}"); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } @@ -285,9 +348,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests // Arrange var expectedError = "[\"1\"," + "false," + - "\"There was an exception invoking \\u0027ReceiveTrivial\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.JSInteropDetailedErrors\\u0027\"]"; + "\"There was an exception invoking \\u0027ReceiveTrivial\\u0027 on assembly \\u0027BasicTestApp\\u0027. For more details turn on detailed exceptions in \\u0027CircuitOptions.DetailedErrors\\u0027\"]"; - var (interopCalls, batches) = ConfigureClient(); + var (_, dotNetCompletions, batches) = ConfigureClient(); await GoToTestComponent(batches); // Act @@ -299,10 +362,161 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests "[ { \"data\": {\"}} ]"); // Assert - Assert.Single(interopCalls, (0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", expectedError)); + Assert.Single(dotNetCompletions, expectedError); await ValidateClientKeepsWorking(Client, batches); } + [Fact] + public async Task DispatchingEventsWithInvalidPayloadsDoesNotCrashTheCircuit() + { + // Arrange + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name)); + + // Act + await Client.HubConnection.InvokeAsync( + "DispatchBrowserEvent", + null, + null); + + Assert.Contains( + (LogLevel.Debug, "DispatchEventFailedToParseEventDescriptor"), + logEvents); + + await ValidateClientKeepsWorking(Client, batches); + } + + [Fact] + public async Task DispatchingEventsWithInvalidEventArgs() + { + // Arrange + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name)); + + // Act + var browserDescriptor = new RendererRegistryEventDispatcher.BrowserEventDescriptor() + { + BrowserRendererId = 0, + EventHandlerId = 6, + EventArgsType = "mouse", + }; + + await Client.HubConnection.InvokeAsync( + "DispatchBrowserEvent", + JsonSerializer.Serialize(browserDescriptor, TestJsonSerializerOptionsProvider.Options), + "{Invalid:{\"payload}"); + + Assert.Contains( + (LogLevel.Debug, "DispatchEventFailedToDispatchEvent"), + logEvents); + + await ValidateClientKeepsWorking(Client, batches); + } + + [Fact] + public async Task DispatchingEventsWithInvalidEventHandlerId() + { + // Arrange + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string eventIdName, Exception exception)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name, wc.Exception)); + + // Act + var mouseEventArgs = new UIMouseEventArgs() + { + Type = "click", + Detail = 1 + }; + var browserDescriptor = new RendererRegistryEventDispatcher.BrowserEventDescriptor() + { + BrowserRendererId = 0, + EventHandlerId = 1, + EventArgsType = "mouse", + }; + + await Client.HubConnection.InvokeAsync( + "DispatchBrowserEvent", + JsonSerializer.Serialize(browserDescriptor, TestJsonSerializerOptionsProvider.Options), + JsonSerializer.Serialize(mouseEventArgs, TestJsonSerializerOptionsProvider.Options)); + + Assert.Contains( + logEvents, + e => e.eventIdName == "DispatchEventFailedToDispatchEvent" && e.logLevel == LogLevel.Debug && + e.exception is ArgumentException ae && ae.Message.Contains("There is no event handler with ID 1")); + + await ValidateClientKeepsWorking(Client, batches); + } + + [Fact] + public async Task DispatchingEventThroughJSInterop() + { + // Arrange + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string eventIdName)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name)); + + // Act + var mouseEventArgs = new UIMouseEventArgs() + { + Type = "click", + Detail = 1 + }; + var browserDescriptor = new RendererRegistryEventDispatcher.BrowserEventDescriptor() + { + BrowserRendererId = 0, + EventHandlerId = 1, + EventArgsType = "mouse", + }; + + var serializerOptions = TestJsonSerializerOptionsProvider.Options; + var uiArgs = JsonSerializer.Serialize(mouseEventArgs, serializerOptions); + + await Assert.ThrowsAsync(() => Client.InvokeDotNetMethod( + 0, + "Microsoft.AspNetCore.Components.Web", + "DispatchEvent", + null, + JsonSerializer.Serialize(new object[] { browserDescriptor, uiArgs }, serializerOptions))); + + Assert.Contains( + (LogLevel.Debug, "DispatchEventThroughJSInterop"), + logEvents); + + await ValidateClientKeepsWorking(Client, batches); + } + + + [Fact] + public async Task EventHandlerThrowsSyncExceptionTerminatesTheCircuit() + { + // Arrange + var (interopCalls, dotNetCompletions, batches) = ConfigureClient(); + await GoToTestComponent(batches); + var sink = _serverFixture.Host.Services.GetRequiredService(); + var logEvents = new List<(LogLevel logLevel, string eventIdName, Exception exception)>(); + sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name, wc.Exception)); + + // Act + await Client.ClickAsync("event-handler-throw-sync"); + + Assert.Contains( + logEvents, + e => LogLevel.Warning == e.logLevel && + "UnhandledExceptionInCircuit" == e.eventIdName && + "Handler threw an exception" == e.exception.Message); + + await ValidateClientKeepsWorking(Client, batches); + } private Task ValidateClientKeepsWorking(BlazorClient Client, List<(int, int, byte[])> batches) => ValidateClientKeepsWorking(Client, () => batches.Count); @@ -325,13 +539,15 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests Assert.Equal(2, batches.Count); } - private (List<(int, string, string)>, List<(int, int, byte[])>) ConfigureClient() + private (List<(int id, string identifier, string args)>, List, List<(int, int, byte[])>) ConfigureClient() { var interopCalls = new List<(int, string, string)>(); Client.JSInterop += (int arg1, string arg2, string arg3) => interopCalls.Add((arg1, arg2, arg3)); var batches = new List<(int, int, byte[])>(); Client.RenderBatchReceived += (id, renderer, data) => batches.Add((id, renderer, data)); - return (interopCalls, batches); + var endInvokeDotNetCompletions = new List(); + Client.DotNetInteropCompletion += (completion) => endInvokeDotNetCompletions.Add(completion); + return (interopCalls, endInvokeDotNetCompletions, batches); } } } diff --git a/src/Components/test/E2ETest/ServerExecutionTests/PrerenderingTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/PrerenderingTest.cs index b7b6d361c8..a7bbc8b9da 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/PrerenderingTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/PrerenderingTest.cs @@ -1,6 +1,11 @@ // Copyright (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 BasicTestApp; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; @@ -10,16 +15,15 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests { - public class PrerenderingTest : ServerTestBase + [Collection("auth")] // Because auth uses cookies, this can't run in parallel with other auth tests + public class PrerenderingTest : BasicTestAppTestBase { public PrerenderingTest( BrowserFixture browserFixture, - AspNetSiteServerFixture serverFixture, + ToggleExecutionModeServerFixture serverFixture, ITestOutputHelper output) - : base(browserFixture, serverFixture, output) + : base(browserFixture, serverFixture.WithServerExecution(), output) { - _serverFixture.Environment = AspNetEnvironment.Development; - _serverFixture.BuildWebHostMethod = TestServer.Program.BuildWebHost; } [Fact] @@ -55,6 +59,62 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests Browser.Equal("Hello from interop call", () => Browser.FindElement(By.Id("val-set-by-interop")).GetAttribute("value")); } + [Fact] + public void CanReadUrlHashOnlyOnceConnected() + { + var urlWithoutHash = "prerendered/show-uri?my=query&another=value"; + var url = $"{urlWithoutHash}#some/hash?tokens"; + + // The server doesn't receive the hash part of the URL, so you can't + // read it during prerendering + Navigate(url); + Browser.Equal( + _serverFixture.RootUri + urlWithoutHash, + () => Browser.FindElement(By.TagName("strong")).Text); + + // Once connected, you do have access to the full URL + BeginInteractivity(); + Browser.Equal( + _serverFixture.RootUri + url, + () => Browser.FindElement(By.TagName("strong")).Text); + } + + [Theory] + [InlineData("base/relative", "prerendered/base/relative")] + [InlineData("/root/relative", "/root/relative")] + [InlineData("http://absolute/url", "http://absolute/url")] + public async Task CanRedirectDuringPrerendering(string destinationParam, string expectedRedirectionLocation) + { + var requestUri = new Uri( + _serverFixture.RootUri, + "prerendered/prerendered-redirection?destination=" + destinationParam); + + var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false }); + var response = await httpClient.GetAsync(requestUri); + + var expectedUri = new Uri(_serverFixture.RootUri, expectedRedirectionLocation); + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + Assert.Equal(expectedUri, response.Headers.Location); + } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Bert")] + [InlineData("Bert", null)] + [InlineData("Bert", "Treb")] + public void CanAccessAuthenticationStateDuringStaticPrerendering(string initialUsername, string interactiveUsername) + { + // See that the authentication state is usable during the initial prerendering + SignInAs(initialUsername, null); + Navigate("/prerendered/prerendered-transition"); + Browser.Equal($"Hello, {initialUsername ?? "anonymous"}!", () => Browser.FindElement(By.TagName("h1")).Text); + + // See that during connection, we update to whatever the latest authentication state now is + SignInAs(interactiveUsername, null, useSeparateTab: true); + BeginInteractivity(); + Browser.Equal($"Hello, {interactiveUsername ?? "anonymous"}!", () => Browser.FindElement(By.TagName("h1")).Text); + } + private void BeginInteractivity() { Browser.FindElement(By.Id("load-boot-script")).Click(); diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerAuthTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerAuthTest.cs new file mode 100644 index 0000000000..6bbdfbfa54 --- /dev/null +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerAuthTest.cs @@ -0,0 +1,65 @@ +// Copyright (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.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.Components.E2ETest.Tests; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Support.UI; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests +{ + public class ServerAuthTest : AuthTest + { + public ServerAuthTest(BrowserFixture browserFixture, ToggleExecutionModeServerFixture serverFixture, ITestOutputHelper output) + : base(browserFixture, serverFixture.WithServerExecution(), output) + { + } + + [Theory(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")] + [InlineData(null, null)] + [InlineData(null, "Someone")] + [InlineData("Someone", null)] + [InlineData("Someone", "Someone")] + public void UpdatesAuthenticationStateWhenReconnecting( + string usernameBefore, string usernameAfter) + { + // Establish state before disconnection + SignInAs(usernameBefore, usernameBefore == null ? null : "TestRole"); + var appElement = MountAndNavigateToAuthTest(AuthorizeViewCases); + AssertState(usernameBefore); + + // Change authentication state and force reconnection + SignInAs(usernameAfter, usernameAfter == null ? null : "TestRole", useSeparateTab: true); + PerformReconnection(); + AssertState(usernameAfter); + + void AssertState(string username) + { + if (username == null) + { + Browser.Equal("You're not authorized, anonymous", () => + appElement.FindElement(By.CssSelector("#authorize-role .not-authorized")).Text); + } + else + { + Browser.Equal($"Welcome, {username}!", () => + appElement.FindElement(By.CssSelector("#authorize-role .authorized")).Text); + } + } + } + + private void PerformReconnection() + { + ((IJavaScriptExecutor)Browser).ExecuteScript("Blazor._internal.forceCloseConnection()"); + + // Wait until the reconnection dialog has been shown but is now hidden + new WebDriverWait(Browser, TimeSpan.FromSeconds(10)) + .Until(driver => driver.FindElement(By.Id("components-reconnect-modal"))?.GetCssValue("display") == "none"); + } + } +} diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerInteropTestDefaultExceptionsBehavior.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerInteropTestDefaultExceptionsBehavior.cs index 1f725fd0bc..15ed860c8c 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/ServerInteropTestDefaultExceptionsBehavior.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerInteropTestDefaultExceptionsBehavior.cs @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests string GetExpectedMessage(string method) => $"\"There was an exception invoking '{method}' on assembly 'BasicTestApp'. For more details turn on " + - $"detailed exceptions in '{typeof(CircuitOptions).Name}.{nameof(CircuitOptions.JSInteropDetailedErrors)}'\""; + $"detailed exceptions in '{typeof(CircuitOptions).Name}.{nameof(CircuitOptions.DetailedErrors)}'\""; } } } diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerSideAppTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerSideAppTest.cs index d68a65234d..4dba75b10c 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/ServerSideAppTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerSideAppTest.cs @@ -138,28 +138,24 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests } } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")] public void ReconnectUI() { Browser.FindElement(By.LinkText("Counter")).Click(); + var javascript = (IJavaScriptExecutor)Browser; - javascript.ExecuteScript(@" -window.modalDisplayState = []; -window.Blazor.circuitHandlers.push({ - onConnectionUp: () => window.modalDisplayState.push(document.getElementById('components-reconnect-modal').style.display), - onConnectionDown: () => window.modalDisplayState.push(document.getElementById('components-reconnect-modal').style.display) -}); -window.Blazor._internal.forceCloseConnection();"); + javascript.ExecuteScript("Blazor._internal.forceCloseConnection()"); - new WebDriverWait(Browser, TimeSpan.FromSeconds(10)).Until( - driver => (long)javascript.ExecuteScript("console.log(window.modalDisplayState); return window.modalDisplayState.length") == 2); + // We should see the 'reconnecting' UI appear + var reconnectionDialog = WaitUntilReconnectionDialogExists(); + Browser.True(() => reconnectionDialog.GetCssValue("display") == "block"); - var states = (string)javascript.ExecuteScript("return window.modalDisplayState.join(',')"); - - Assert.Equal("block,none", states); + // Then it should disappear + new WebDriverWait(Browser, TimeSpan.FromSeconds(10)) + .Until(driver => reconnectionDialog.GetCssValue("display") == "none"); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")] public void RendersContinueAfterReconnect() { Browser.FindElement(By.LinkText("Ticker")).Click(); @@ -169,16 +165,17 @@ window.Blazor._internal.forceCloseConnection();"); var initialValue = element.Text; var javascript = (IJavaScriptExecutor)Browser; - javascript.ExecuteScript(@" -window.connectionUp = false; -window.Blazor.circuitHandlers.push({ - onConnectionUp: () => window.connectionUp = true -}); -window.Blazor._internal.forceCloseConnection();"); + javascript.ExecuteScript("Blazor._internal.forceCloseConnection()"); - new WebDriverWait(Browser, TimeSpan.FromSeconds(10)).Until( - driver => (bool)javascript.ExecuteScript("return window.connectionUp")); + // We should see the 'reconnecting' UI appear + var reconnectionDialog = WaitUntilReconnectionDialogExists(); + Browser.True(() => reconnectionDialog.GetCssValue("display") == "block"); + // Then it should disappear + new WebDriverWait(Browser, TimeSpan.FromSeconds(10)) + .Until(driver => reconnectionDialog.GetCssValue("display") == "none"); + + // We should receive a render that occurred while disconnected var currentValue = element.Text; Assert.NotEqual(initialValue, currentValue); @@ -187,11 +184,14 @@ window.Blazor._internal.forceCloseConnection();"); _ => element.Text != currentValue); } + // Since we've removed stateful prerendering, the name which is passed in + // during prerendering cannot be retained. The first interactive render + // will remove it. [Fact] - public void RendersContinueAfterPrerendering() + public void RendersDoNotPreserveState() { Browser.FindElement(By.LinkText("Greeter")).Click(); - Browser.Equal("Hello Guest", () => Browser.FindElement(By.ClassName("greeting")).Text); + Browser.Equal("Hello", () => Browser.FindElement(By.ClassName("greeting")).Text); } [Fact] @@ -204,5 +204,13 @@ window.Blazor._internal.forceCloseConnection();"); Browser.True(() => Browser.Manage().Logs.GetLog(LogType.Browser) .Any(l => l.Level == LogLevel.Info && l.Message.Contains("Connection disconnected."))); } + + private IWebElement WaitUntilReconnectionDialogExists() + { + IWebElement reconnectionDialog = null; + new WebDriverWait(Browser, TimeSpan.FromSeconds(10)) + .Until(driver => (reconnectionDialog = driver.FindElement(By.Id("components-reconnect-modal"))) != null); + return reconnectionDialog; + } } } diff --git a/src/Components/test/E2ETest/ServerExecutionTests/TestSubclasses.cs b/src/Components/test/E2ETest/ServerExecutionTests/TestSubclasses.cs index c99c1d3828..5f22a585a1 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/TestSubclasses.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/TestSubclasses.cs @@ -83,12 +83,4 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests { } } - - public class ServerAuthTest : AuthTest - { - public ServerAuthTest(BrowserFixture browserFixture, ToggleExecutionModeServerFixture serverFixture, ITestOutputHelper output) - : base(browserFixture, serverFixture.WithServerExecution(), output) - { - } - } } diff --git a/src/Components/test/E2ETest/Tests/AuthTest.cs b/src/Components/test/E2ETest/Tests/AuthTest.cs index 9c2c26b0c6..deaa6bfb64 100644 --- a/src/Components/test/E2ETest/Tests/AuthTest.cs +++ b/src/Components/test/E2ETest/Tests/AuthTest.cs @@ -11,15 +11,16 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.Components.E2ETest.Tests { + [Collection("auth")] // Because auth uses cookies, this can't run in parallel with other auth tests public class AuthTest : BasicTestAppTestBase { // These strings correspond to the links in BasicTestApp\AuthTest\Links.razor - const string CascadingAuthenticationStateLink = "Cascading authentication state"; - const string AuthorizeViewCases = "AuthorizeView cases"; - const string PageAllowingAnonymous = "Page allowing anonymous"; - const string PageRequiringAuthorization = "Page requiring any authentication"; - const string PageRequiringPolicy = "Page requiring policy"; - const string PageRequiringRole = "Page requiring role"; + protected const string CascadingAuthenticationStateLink = "Cascading authentication state"; + protected const string AuthorizeViewCases = "AuthorizeView cases"; + protected const string PageAllowingAnonymous = "Page allowing anonymous"; + protected const string PageRequiringAuthorization = "Page requiring any authentication"; + protected const string PageRequiringPolicy = "Page requiring policy"; + protected const string PageRequiringRole = "Page requiring role"; public AuthTest( BrowserFixture browserFixture, @@ -184,7 +185,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests appElement.FindElement(By.CssSelector("#auth-failure")).Text); } - IWebElement MountAndNavigateToAuthTest(string authLinkText) + protected IWebElement MountAndNavigateToAuthTest(string authLinkText) { Navigate(ServerPathBase); var appElement = MountTestComponent(); @@ -192,15 +193,5 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests appElement.FindElement(By.LinkText(authLinkText)).Click(); return appElement; } - - void SignInAs(string usernameOrNull, string rolesOrNull) - { - const string authenticationPageUrl = "/Authentication"; - var baseRelativeUri = usernameOrNull == null - ? $"{authenticationPageUrl}?signout=true" - : $"{authenticationPageUrl}?username={usernameOrNull}&roles={rolesOrNull}"; - Navigate(baseRelativeUri); - WaitUntilExists(By.CssSelector("h1#authentication")); - } } } diff --git a/src/Components/test/E2ETest/Tests/BindTest.cs b/src/Components/test/E2ETest/Tests/BindTest.cs index ce28c7891f..0ca35690bb 100644 --- a/src/Components/test/E2ETest/Tests/BindTest.cs +++ b/src/Components/test/E2ETest/Tests/BindTest.cs @@ -770,11 +770,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); - // Clear textbox; value updates to emtpy because that's what we do for `default` when there's a format + // Clear textbox; value updates to the default target.Clear(); target.SendKeys("\t"); expected = default; - Browser.Equal(string.Empty, () => target.GetAttribute("value")); + Browser.Equal("01-01", () => target.GetAttribute("value")); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); @@ -829,10 +829,10 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); - // Clear textbox; value updates to emtpy because that's what we do for `default` when there's a format + // Clear textbox; value updates to the default target.Clear(); expected = default; - Browser.Equal(string.Empty, () => target.GetAttribute("value")); + Browser.Equal("01-01", () => target.GetAttribute("value")); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); diff --git a/src/Components/test/E2ETest/Tests/RoutingTest.cs b/src/Components/test/E2ETest/Tests/RoutingTest.cs index ce0dc725e6..dd161bc7a3 100644 --- a/src/Components/test/E2ETest/Tests/RoutingTest.cs +++ b/src/Components/test/E2ETest/Tests/RoutingTest.cs @@ -226,10 +226,6 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests AssertHighlightedLinks("With parameters", "With more parameters"); // Can remove parameters while remaining on same page - // WARNING: This only works because the WithParameters component overrides SetParametersAsync - // and explicitly resets its parameters to default when each new set of parameters arrives. - // Without that, the page would retain the old value. - // See https://github.com/aspnet/AspNetCore/issues/6864 where we reverted the logic to auto-reset. app.FindElement(By.LinkText("With parameters")).Click(); Browser.Equal("Your full name is Abc .", () => app.FindElement(By.Id("test-info")).Text); AssertHighlightedLinks("With parameters"); @@ -373,9 +369,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests } [Fact] - public void UsingUriHelperWithoutRouterWorks() + public void UsingNavigationManagerWithoutRouterWorks() { - var app = MountTestComponent(); + var app = MountTestComponent(); var initialUrl = Browser.Url; Browser.Equal(Browser.Url, () => app.FindElement(By.Id("test-info")).Text); @@ -388,6 +384,19 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Browser.Equal(initialUrl, () => app.FindElement(By.Id("test-info")).Text); } + [Fact] + public void UriHelperCanReadAbsoluteUriIncludingHash() + { + var app = MountTestComponent(); + Browser.Equal(Browser.Url, () => app.FindElement(By.Id("test-info")).Text); + + var uri = "/mytestpath?my=query&another#some/hash?tokens"; + var expectedAbsoluteUri = $"{_serverFixture.RootUri}subdir{uri}"; + + SetUrlViaPushState(uri); + Browser.Equal(expectedAbsoluteUri, () => app.FindElement(By.Id("test-info")).Text); + } + [Fact] public void CanArriveAtRouteWithExtension() { @@ -409,6 +418,40 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Assert.Equal("Oops, that component wasn't found!", app.FindElement(By.Id("test-info")).Text); } + [Fact] + public void ResetsScrollPositionWhenPerformingInternalNavigation_LinkClick() + { + SetUrlViaPushState("/LongPage1"); + var app = MountTestComponent(); + Browser.Equal("This is a long page you can scroll.", () => app.FindElement(By.Id("test-info")).Text); + BrowserScrollY = 500; + Browser.True(() => BrowserScrollY > 300); // Exact position doesn't matter + + app.FindElement(By.LinkText("Long page 2")).Click(); + Browser.Equal("This is another long page you can scroll.", () => app.FindElement(By.Id("test-info")).Text); + Browser.Equal(0, () => BrowserScrollY); + } + + [Fact] + public void ResetsScrollPositionWhenPerformingInternalNavigation_ProgrammaticNavigation() + { + SetUrlViaPushState("/LongPage1"); + var app = MountTestComponent(); + Browser.Equal("This is a long page you can scroll.", () => app.FindElement(By.Id("test-info")).Text); + BrowserScrollY = 500; + Browser.True(() => BrowserScrollY > 300); // Exact position doesn't matter + + app.FindElement(By.Id("go-to-longpage2")).Click(); + Browser.Equal("This is another long page you can scroll.", () => app.FindElement(By.Id("test-info")).Text); + Browser.Equal(0, () => BrowserScrollY); + } + + private long BrowserScrollY + { + get => (long)((IJavaScriptExecutor)Browser).ExecuteScript("return window.scrollY"); + set => ((IJavaScriptExecutor)Browser).ExecuteScript($"window.scrollTo(0, {value})"); + } + private string SetUrlViaPushState(string relativeUri) { var pathBaseWithoutHash = ServerPathBase.Split('#')[0]; diff --git a/src/Components/test/Ignitor.Test/RenderBatchReaderTest.cs b/src/Components/test/Ignitor.Test/RenderBatchReaderTest.cs index b5e8c35ba4..dbd46a0e16 100644 --- a/src/Components/test/Ignitor.Test/RenderBatchReaderTest.cs +++ b/src/Components/test/Ignitor.Test/RenderBatchReaderTest.cs @@ -6,11 +6,10 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; -using Castle.Core.Logging; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; -using Microsoft.AspNetCore.Components.Server.Circuits; +using Microsoft.AspNetCore.Components.Web.Rendering; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Xunit; @@ -103,7 +102,7 @@ namespace Ignitor RenderTreeEdit.UpdateMarkup(108, 109), RenderTreeEdit.RemoveAttribute(110, "Some removed attribute"), // To test deduplication }; - var editsBuilder = new ArrayBuilder(); + var editsBuilder = new Microsoft.AspNetCore.Components.RenderTree.ArrayBuilder(); editsBuilder.Append(edits, 0, edits.Length); var editsSegment = editsBuilder.ToSegment(1, edits.Length); // Skip first to show offset is respected var bytes = RoundTripSerialize(new RenderBatch( @@ -332,7 +331,7 @@ namespace Ignitor public void Attach(RenderHandle renderHandle) => throw new NotImplementedException(); - public Task SetParametersAsync(ParameterCollection parameters) + public Task SetParametersAsync(ParameterView parameters) => throw new NotImplementedException(); } diff --git a/src/Components/test/testassets/BasicTestApp/AfterRenderInteropComponent.razor b/src/Components/test/testassets/BasicTestApp/AfterRenderInteropComponent.razor index eafeb595f7..57f99f485a 100644 --- a/src/Components/test/testassets/BasicTestApp/AfterRenderInteropComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/AfterRenderInteropComponent.razor @@ -4,7 +4,7 @@ @code { - ElementRef myInput; + ElementReference myInput; protected override void OnAfterRender() { diff --git a/src/Components/test/testassets/BasicTestApp/AuthTest/AuthRouter.razor b/src/Components/test/testassets/BasicTestApp/AuthTest/AuthRouter.razor index 73a2b6260d..5ec7bbe529 100644 --- a/src/Components/test/testassets/BasicTestApp/AuthTest/AuthRouter.razor +++ b/src/Components/test/testassets/BasicTestApp/AuthTest/AuthRouter.razor @@ -1,5 +1,5 @@ @using Microsoft.AspNetCore.Components.Routing -@inject IUriHelper UriHelper +@inject NavigationManager NavigationManager @* This router is independent of any other router that may exist within the same project. @@ -10,12 +10,12 @@ - Authorizing... - + Authorizing... +
Sorry, @(context.User.Identity.Name ?? "anonymous"), you're not authorized.
-
+
@@ -27,11 +27,11 @@ { // Start at AuthHome, not at any other component in the same app that happens to // register itself for the route "" - var absoluteUriPath = new Uri(UriHelper.GetAbsoluteUri()).GetLeftPart(UriPartial.Path); - var relativeUri = UriHelper.ToBaseRelativePath(UriHelper.GetBaseUri(), absoluteUriPath); + var absoluteUriPath = new Uri(NavigationManager.Uri).GetLeftPart(UriPartial.Path); + var relativeUri = NavigationManager.ToBaseRelativePath(absoluteUriPath); if (relativeUri == string.Empty) { - UriHelper.NavigateTo("AuthHome"); + NavigationManager.NavigateTo("AuthHome"); } } } diff --git a/src/Components/test/testassets/BasicTestApp/BindCasesComponent.razor b/src/Components/test/testassets/BasicTestApp/BindCasesComponent.razor index 6f132f6f6a..5cdd9087ea 100644 --- a/src/Components/test/testassets/BasicTestApp/BindCasesComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/BindCasesComponent.razor @@ -1,5 +1,7 @@

Bind cases

+@* There are a mix of cases here using bind and bind-value for coverage *@ +

Textbox

Initially blank: @@ -32,7 +34,7 @@

Nullable int: - + @textboxNullableIntValue

@@ -50,7 +52,7 @@

float: - + @textboxFloatValue

@@ -74,7 +76,7 @@

decimal: - + @textboxDecimalValue

@@ -119,7 +121,7 @@

Nullable DateTime: - + @textboxNullableDateTimeValue

@@ -149,7 +151,7 @@

DateTime (format): - + @textboxDateTimeFormatValue

@@ -161,7 +163,7 @@

DateTime (format / invalid value): - + @textboxDateTimeFormatInvalidValue

diff --git a/src/Components/test/testassets/BasicTestApp/BindMethods.cs b/src/Components/test/testassets/BasicTestApp/BindMethods.cs new file mode 100644 index 0000000000..78ec6cdd35 --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/BindMethods.cs @@ -0,0 +1,11 @@ +namespace Microsoft.AspNetCore.Components +{ + // This is a temporary workaround for the fact that public previews of VS look for + // this type. Without this the tooling won't understand bind or event handlers. + // + // This has already gotten better in 16.3 and we look for IComponent rather + // than specific implementation details. + public static class BindMethods + { + } +} diff --git a/src/Components/test/testassets/BasicTestApp/CulturePicker.razor b/src/Components/test/testassets/BasicTestApp/CulturePicker.razor index aacf90bb12..6e20528c69 100644 --- a/src/Components/test/testassets/BasicTestApp/CulturePicker.razor +++ b/src/Components/test/testassets/BasicTestApp/CulturePicker.razor @@ -1,4 +1,4 @@ -@inject IUriHelper UriHelper +@inject NavigationManager NavigationManager

Select your language

@code { - void OnSelected(UIChangeEventArgs e) + void OnSelected(ChangeEventArgs e) { // Included fragment to preserve choice of Blazor client or server. - var redirect = new Uri(UriHelper.GetAbsoluteUri()).GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped); + var redirect = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped); var query = $"?culture={Uri.EscapeDataString((string)e.Value)}&redirectUri={redirect}"; - UriHelper.NavigateTo("/Culture/SetCulture" + query, forceLoad: true); + NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true); } } diff --git a/src/Components/test/testassets/BasicTestApp/DuplicateAttributesComponent.razor b/src/Components/test/testassets/BasicTestApp/DuplicateAttributesComponent.razor index 80f8521de7..8d7bcc2e33 100644 --- a/src/Components/test/testassets/BasicTestApp/DuplicateAttributesComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/DuplicateAttributesComponent.razor @@ -2,12 +2,12 @@ + UnmatchedValues="elementValues"/>
diff --git a/src/Components/test/testassets/BasicTestApp/DuplicateAttributesOnElementChildComponent.razor b/src/Components/test/testassets/BasicTestApp/DuplicateAttributesOnElementChildComponent.razor index 27048982f1..d68e5f0619 100644 --- a/src/Components/test/testassets/BasicTestApp/DuplicateAttributesOnElementChildComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/DuplicateAttributesOnElementChildComponent.razor @@ -14,10 +14,10 @@ else } @code { - [Parameter] public string StringAttributeBefore { get; private set; } - [Parameter] public bool BoolAttributeBefore { get; private set; } - [Parameter] public string StringAttributeAfter { get; private set; } - [Parameter] public bool? BoolAttributeAfter { get; private set; } + [Parameter] public string StringAttributeBefore { get; set; } + [Parameter] public bool BoolAttributeBefore { get; set; } + [Parameter] public string StringAttributeAfter { get; set; } + [Parameter] public bool? BoolAttributeAfter { get; set; } - [Parameter(CaptureUnmatchedValues = true)] public Dictionary UnmatchedValues { get; private set; } + [Parameter(CaptureUnmatchedValues = true)] public Dictionary UnmatchedValues { get; set; } } diff --git a/src/Components/test/testassets/BasicTestApp/ElementRefComponent.razor b/src/Components/test/testassets/BasicTestApp/ElementRefComponent.razor index f1d320b795..06ece3a788 100644 --- a/src/Components/test/testassets/BasicTestApp/ElementRefComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/ElementRefComponent.razor @@ -28,7 +28,7 @@ @code { int _count = 0; bool _toggleCapturedElementPresence = true; - ElementRef _myInput; + ElementReference _myInput; async Task MakeInteropCall() { diff --git a/src/Components/test/testassets/BasicTestApp/FormsTest/NotifyPropertyChangedValidationComponent.razor b/src/Components/test/testassets/BasicTestApp/FormsTest/NotifyPropertyChangedValidationComponent.razor index 8cc8859ad9..1fd89a851f 100644 --- a/src/Components/test/testassets/BasicTestApp/FormsTest/NotifyPropertyChangedValidationComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/FormsTest/NotifyPropertyChangedValidationComponent.razor @@ -18,11 +18,11 @@

User name: - +

Accept terms: - +

diff --git a/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor b/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor index 5182f53a49..aa8ccfbe54 100644 --- a/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor @@ -5,10 +5,10 @@

- User name: + User name:

- Accept terms: + Accept terms:

diff --git a/src/Components/test/testassets/BasicTestApp/GlobalizationBindCases.razor b/src/Components/test/testassets/BasicTestApp/GlobalizationBindCases.razor index 41877e417d..9f4dadf7a9 100644 --- a/src/Components/test/testassets/BasicTestApp/GlobalizationBindCases.razor +++ b/src/Components/test/testassets/BasicTestApp/GlobalizationBindCases.razor @@ -3,6 +3,8 @@

Globalization Bind Cases

Culture is: @System.Globalization.CultureInfo.CurrentCulture.Name

+@* There are a mix of cases here using bind and bind-value for coverage *@ +

Numbers using bind in text fields

@@ -10,7 +12,7 @@ @inputTypeTextInt
- decimal: + decimal: @inputTypeTextDecimal
@@ -22,7 +24,7 @@ @inputTypeTextDateTime
- DateTimeOffset: + DateTimeOffset: @inputTypeTextDateTimeOffset
@@ -30,11 +32,11 @@

Numbers using bind in number fields

- int: + int: @inputTypeNumberInt
- decimal: + decimal: @inputTypeNumberDecimal
@@ -43,12 +45,12 @@

Dates using bind in date fields

DateTime: - + @inputTypeDateDateTime
- DateTimeOffset: - + DateTimeOffset: + @inputTypeDateDateTimeOffset
diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor index df71e0cb93..fe8608105c 100644 --- a/src/Components/test/testassets/BasicTestApp/Index.razor +++ b/src/Components/test/testassets/BasicTestApp/Index.razor @@ -57,9 +57,8 @@ + - - diff --git a/src/Components/test/testassets/BasicTestApp/InteropOnInitializationComponent.razor b/src/Components/test/testassets/BasicTestApp/InteropOnInitializationComponent.razor index 8b20721596..ae3f3491e3 100644 --- a/src/Components/test/testassets/BasicTestApp/InteropOnInitializationComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/InteropOnInitializationComponent.razor @@ -24,7 +24,7 @@ @code { string infoFromJs; - ElementRef myElem; + ElementReference myElem; protected override async Task OnAfterRenderAsync() { diff --git a/src/Components/test/testassets/BasicTestApp/PrerenderedRedirection.razor b/src/Components/test/testassets/BasicTestApp/PrerenderedRedirection.razor new file mode 100644 index 0000000000..78bd99eabd --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/PrerenderedRedirection.razor @@ -0,0 +1,16 @@ +@page "/prerendered-redirection" +@inject NavigationManager NavigationManager + +@{ + throw new InvalidOperationException("The rendering logic should never be executed"); +} + +@code { + protected override Task OnInitializedAsync() + { + var uri = NavigationManager.Uri; + var destination = uri.Substring(uri.IndexOf("?destination=") + 13); + NavigationManager.NavigateTo(destination); + return Task.CompletedTask; + } +} diff --git a/src/Components/test/testassets/BasicTestApp/PrerenderedToInteractiveTransition.razor b/src/Components/test/testassets/BasicTestApp/PrerenderedToInteractiveTransition.razor index 192efbacd0..af6010e649 100644 --- a/src/Components/test/testassets/BasicTestApp/PrerenderedToInteractiveTransition.razor +++ b/src/Components/test/testassets/BasicTestApp/PrerenderedToInteractiveTransition.razor @@ -2,18 +2,23 @@ @using Microsoft.AspNetCore.Components @inject IComponentContext ComponentContext -

Hello

+ + +

Hello, @context.User.Identity.Name!

+

Hello, anonymous!

+
-

- Current state: - @(ComponentContext.IsConnected ? "connected" : "not connected") -

+

+ Current state: + @(ComponentContext.IsConnected ? "connected" : "not connected") +

-

- Clicks: - @count - -

+

+ Clicks: + @count + +

+
@code { int count; diff --git a/src/Components/test/testassets/BasicTestApp/Program.cs b/src/Components/test/testassets/BasicTestApp/Program.cs index 5e85aca979..cebb226e7c 100644 --- a/src/Components/test/testassets/BasicTestApp/Program.cs +++ b/src/Components/test/testassets/BasicTestApp/Program.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.Globalization; using Microsoft.AspNetCore.Blazor.Hosting; namespace BasicTestApp @@ -9,6 +10,9 @@ namespace BasicTestApp { public static void 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(); } diff --git a/src/Components/test/testassets/BasicTestApp/RouterTest/Links.razor b/src/Components/test/testassets/BasicTestApp/RouterTest/Links.razor index 64811b666b..c5a5626382 100644 --- a/src/Components/test/testassets/BasicTestApp/RouterTest/Links.razor +++ b/src/Components/test/testassets/BasicTestApp/RouterTest/Links.razor @@ -1,5 +1,5 @@ @using Microsoft.AspNetCore.Components.Routing -@inject Microsoft.AspNetCore.Components.IUriHelper uriHelper +@inject NavigationManager NavigationManager -

"); +

An error occurred while starting the application.

+"); +#nullable restore #line 226 "ErrorPage.cshtml" - Write("An error occurred while starting the application."); - -#line default -#line hidden - WriteLiteral("\r\n"); -#line 227 "ErrorPage.cshtml" - - -#line default -#line hidden - -#line 227 "ErrorPage.cshtml" foreach (var errorDetail in Model.ErrorDetails) { #line default #line hidden - +#nullable disable WriteLiteral("
"); -#line 229 "ErrorPage.cshtml" +#nullable restore +#line 228 "ErrorPage.cshtml" Write(errorDetail.Error.GetType().Name); #line default #line hidden +#nullable disable WriteLiteral(": "); -#line 229 "ErrorPage.cshtml" - Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); +#nullable restore +#line 228 "ErrorPage.cshtml" + Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); #line default #line hidden - +#nullable disable WriteLiteral("
\r\n"); -#line 230 "ErrorPage.cshtml" - - -#line default -#line hidden - -#line 230 "ErrorPage.cshtml" - - var firstFrame = errorDetail.StackFrames.FirstOrDefault(); - if (firstFrame != null) - { - location = firstFrame.Function; - } - - -#line default -#line hidden - -#line 236 "ErrorPage.cshtml" +#nullable restore +#line 229 "ErrorPage.cshtml" + var firstFrame = errorDetail.StackFrames.FirstOrDefault(); + if (firstFrame != null) + { + location = firstFrame.Function; + } if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File)) { #line default #line hidden - +#nullable disable WriteLiteral("

"); -#line 239 "ErrorPage.cshtml" +#nullable restore +#line 237 "ErrorPage.cshtml" Write(location); #line default #line hidden +#nullable disable WriteLiteral(" in

\r\n"); -#line 240 "ErrorPage.cshtml" +#nullable restore +#line 238 "ErrorPage.cshtml" } else if (!string.IsNullOrEmpty(location)) { #line default #line hidden - +#nullable disable WriteLiteral("

"); -#line 243 "ErrorPage.cshtml" +#nullable restore +#line 241 "ErrorPage.cshtml" Write(location); #line default #line hidden +#nullable disable WriteLiteral("

\r\n"); -#line 244 "ErrorPage.cshtml" +#nullable restore +#line 242 "ErrorPage.cshtml" } else { #line default #line hidden - - WriteLiteral("

"); -#line 247 "ErrorPage.cshtml" - Write("Unknown location"); - -#line default -#line hidden - WriteLiteral("

\r\n"); -#line 248 "ErrorPage.cshtml" +#nullable disable + WriteLiteral("

Unknown location

\r\n"); +#nullable restore +#line 246 "ErrorPage.cshtml" } var reflectionTypeLoadException = errorDetail.Error as ReflectionTypeLoadException; @@ -413,372 +393,335 @@ WriteAttributeValue("", 4852, firstFrame.File, 4852, 16, false); #line default #line hidden - +#nullable disable WriteLiteral("

Loader Exceptions:

\r\n
    \r\n"); -#line 257 "ErrorPage.cshtml" - - -#line default -#line hidden - -#line 257 "ErrorPage.cshtml" +#nullable restore +#line 255 "ErrorPage.cshtml" foreach (var ex in reflectionTypeLoadException.LoaderExceptions) { #line default #line hidden - +#nullable disable WriteLiteral("
  • "); -#line 259 "ErrorPage.cshtml" +#nullable restore +#line 257 "ErrorPage.cshtml" Write(ex.Message); #line default #line hidden +#nullable disable WriteLiteral("
  • \r\n"); -#line 260 "ErrorPage.cshtml" +#nullable restore +#line 258 "ErrorPage.cshtml" } #line default #line hidden - +#nullable disable WriteLiteral("
\r\n"); -#line 262 "ErrorPage.cshtml" +#nullable restore +#line 260 "ErrorPage.cshtml" } } } #line default #line hidden - +#nullable disable WriteLiteral("
\r\n
    \r\n"); -#line 267 "ErrorPage.cshtml" - - -#line default -#line hidden - -#line 267 "ErrorPage.cshtml" - +#nullable restore +#line 265 "ErrorPage.cshtml" + var exceptionCount = 0; var stackFrameCount = 0; var exceptionDetailId = ""; var frameId = ""; - + #line default #line hidden - - WriteLiteral(" "); -#line 273 "ErrorPage.cshtml" +#nullable disable +#nullable restore +#line 271 "ErrorPage.cshtml" foreach (var errorDetail in Model.ErrorDetails) { - + exceptionCount++; + exceptionDetailId = "exceptionDetail" + exceptionCount; #line default #line hidden - -#line 275 "ErrorPage.cshtml" - - exceptionCount++; - exceptionDetailId = "exceptionDetail" + exceptionCount; - - -#line default -#line hidden - -#line 278 "ErrorPage.cshtml" - - -#line default -#line hidden - +#nullable disable WriteLiteral("
  • \r\n

    "); -#line 280 "ErrorPage.cshtml" +#nullable restore +#line 276 "ErrorPage.cshtml" Write(errorDetail.Error.GetType().Name); #line default #line hidden +#nullable disable WriteLiteral(": "); -#line 280 "ErrorPage.cshtml" +#nullable restore +#line 276 "ErrorPage.cshtml" Write(errorDetail.Error.Message); #line default #line hidden +#nullable disable WriteLiteral("

    \r\n
      \r\n"); -#line 282 "ErrorPage.cshtml" - - -#line default -#line hidden - -#line 282 "ErrorPage.cshtml" +#nullable restore +#line 278 "ErrorPage.cshtml" foreach (var frame in errorDetail.StackFrames) { - + stackFrameCount++; + frameId = "frame" + stackFrameCount; #line default #line hidden - -#line 284 "ErrorPage.cshtml" - - stackFrameCount++; - frameId = "frame" + stackFrameCount; - - -#line default -#line hidden - -#line 287 "ErrorPage.cshtml" - - -#line default -#line hidden - +#nullable disable WriteLiteral("
    • "); -#line 307 "ErrorPage.cshtml" +#nullable restore +#line 301 "ErrorPage.cshtml" Write(line); #line default #line hidden +#nullable disable WriteLiteral("
    • \r\n"); -#line 308 "ErrorPage.cshtml" +#nullable restore +#line 302 "ErrorPage.cshtml" } #line default #line hidden - +#nullable disable WriteLiteral(" \r\n"); -#line 310 "ErrorPage.cshtml" +#nullable restore +#line 304 "ErrorPage.cshtml" } #line default #line hidden - +#nullable disable WriteLiteral("\r\n
\r\n"); -#line 329 "ErrorPage.cshtml" +#nullable restore +#line 323 "ErrorPage.cshtml" } #line default #line hidden - +#nullable disable WriteLiteral(" \r\n"); -#line 331 "ErrorPage.cshtml" +#nullable restore +#line 325 "ErrorPage.cshtml" } #line default #line hidden - +#nullable disable WriteLiteral(@"
  • @@ -786,65 +729,96 @@ WriteAttributeValue("", 8779, frame.Line + 1, 8779, 17, false);
    \r\n
    \r\n
    \r\n \r\n
  • \r\n"); -#line 345 "ErrorPage.cshtml" +#nullable restore +#line 339 "ErrorPage.cshtml" } #line default #line hidden - - WriteLiteral(" \r\n \r\n