Merge branch 'release/5.0' into prkrishn/nullability-feedback
This commit is contained in:
commit
87a51a358a
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
# Test this script using changes in a fork
|
# Test this script using changes in a fork
|
||||||
repository: 'dotnet/runtime'
|
repository: 'dotnet/runtime'
|
||||||
path: runtime
|
path: runtime
|
||||||
ref: release/5.0-rc1
|
ref: release/5.0
|
||||||
- name: Copy
|
- name: Copy
|
||||||
shell: cmd
|
shell: cmd
|
||||||
working-directory: .\runtime\src\libraries\Common\src\System\Net\Http\aspnetcore\
|
working-directory: .\runtime\src\libraries\Common\src\System\Net\Http\aspnetcore\
|
||||||
|
|
|
||||||
257
AspNetCore.sln
257
AspNetCore.sln
|
|
@ -1397,14 +1397,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sockets.BindTests", "src\Se
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "http2cat", "src\Servers\Kestrel\samples\http2cat\http2cat.csproj", "{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "http2cat", "src\Servers\Kestrel\samples\http2cat\http2cat.csproj", "{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuicSampleApp", "src\Servers\Kestrel\samples\QuicSampleApp\QuicSampleApp.csproj", "{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Transport.Quic", "Transport.Quic", "{EE9D0952-6060-4723-B329-94A2950A6762}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Transport.Quic", "Transport.Quic", "{EE9D0952-6060-4723-B329-94A2950A6762}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic", "src\Servers\Kestrel\Transport.Quic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic.csproj", "{132D43A2-067A-4E24-A520-45B9F14DCB8E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic", "src\Servers\Kestrel\Transport.Quic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic.csproj", "{132D43A2-067A-4E24-A520-45B9F14DCB8E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuicSampleClient", "src\Servers\Kestrel\samples\QuicSampleClient\QuicSampleClient.csproj", "{FA8D7CA4-C33B-4409-865F-54192BAC59A4}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Http3SampleApp", "src\Servers\Kestrel\samples\Http3SampleApp\Http3SampleApp.csproj", "{2EC4E939-513F-44CD-A956-498966EAC929}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Http3SampleApp", "src\Servers\Kestrel\samples\Http3SampleApp\Http3SampleApp.csproj", "{2EC4E939-513F-44CD-A956-498966EAC929}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpStress", "src\Servers\Kestrel\stress\HttpStress.csproj", "{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpStress", "src\Servers\Kestrel\stress\HttpStress.csproj", "{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A}"
|
||||||
|
|
@ -1423,13 +1419,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{FED4267E-E5E4-49C5-98DB-8B3F203596EE}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{FED4267E-E5E4-49C5-98DB-8B3F203596EE}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly", "src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj", "{6B2734BF-C61D-4889-ABBF-456A4075D59B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly", "src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj", "{6B2734BF-C61D-4889-ABBF-456A4075D59B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tests", "src\Components\WebAssembly\Sdk\test\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj", "{83371889-9A3E-4D16-AE77-EB4F83BC6374}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tests", "src\Components\WebAssembly\Sdk\test\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj", "{83371889-9A3E-4D16-AE77-EB4F83BC6374}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests", "src\Components\WebAssembly\Sdk\integrationtests\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj", "{525EBCB4-A870-470B-BC90-845306C337D1}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests", "src\Components\WebAssembly\Sdk\integrationtests\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj", "{525EBCB4-A870-470B-BC90-845306C337D1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tools", "src\Components\WebAssembly\Sdk\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj", "{175E5CD8-92D4-46BB-882E-3A930D3302D4}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tools", "src\Components\WebAssembly\Sdk\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj", "{175E5CD8-92D4-46BB-882E-3A930D3302D4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{6126DCE4-9692-4EE2-B240-C65743572995}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{6126DCE4-9692-4EE2-B240-C65743572995}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -1455,7 +1451,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropClient", "src\Grpc\t
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropWebsite", "src\Grpc\test\testassets\InteropWebsite\InteropWebsite.csproj", "{19189670-E206-471D-94F8-7D3D545E5020}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropWebsite", "src\Grpc\test\testassets\InteropWebsite\InteropWebsite.csproj", "{19189670-E206-471D-94F8-7D3D545E5020}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.ConsoleHost", "src\Components\benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{E9408723-E6A9-4715-B906-3B25B0238ABA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.ConsoleHost", "src\Components\benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{E9408723-E6A9-4715-B906-3B25B0238ABA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "src\Servers\IIS\IIS\test\testassets\InProcessWebSite\InProcessWebSite.csproj", "{8DA61885-B95E-4BA1-A752-C79B6597FC44}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "src\Servers\IIS\IIS\test\testassets\InProcessWebSite\InProcessWebSite.csproj", "{8DA61885-B95E-4BA1-A752-C79B6597FC44}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -1483,6 +1479,36 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Watch.
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Watch.BrowserRefresh.Tests", "src\Tools\dotnet-watch\BrowserRefresh\test\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests.csproj", "{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Watch.BrowserRefresh.Tests", "src\Tools\dotnet-watch\BrowserRefresh\test\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests.csproj", "{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{7D2B0799-A634-42AC-AE77-5D167BA51389}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "src\Components\WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{9788C76F-658B-4441-88F8-22C6B86FAD27}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "src\Components\WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{1970D5CD-D9A4-4673-A297-179BB04199F4}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "src\Components\WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{A40350FE-4334-4007-B1C3-6BEB1B070309}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "src\Components\WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Server", "src\Components\WebAssembly\testassets\Wasm.Authentication.Server\Wasm.Authentication.Server.csproj", "{FE5290C7-45DA-46F8-BD74-698E7A161DD6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "src\Components\WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{C1E7F837-6988-43E2-9E1C-7302DB484F99}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7CB09412-C9B0-47E8-A8C3-311AA4CFDE04}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Abstractions", "Abstractions", "{22D7D74B-565D-4047-97B4-F149B1A13350}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "src\HealthChecks\Abstractions\src\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj", "{B06040BC-DA28-4923-8CAC-20EB517D471B}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks", "src\HealthChecks\HealthChecks\src\Microsoft.Extensions.Diagnostics.HealthChecks.csproj", "{55CACC1F-FE96-47C8-8073-91F4CAA55C75}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Tests", "src\HealthChecks\HealthChecks\test\Microsoft.Extensions.Diagnostics.HealthChecks.Tests.csproj", "{7509AA1E-3093-4BEE-984F-E11579E98A11}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.JSInterop.Tests", "src\JSInterop\Microsoft.JSInterop\test\Microsoft.JSInterop.Tests.csproj", "{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -6653,18 +6679,6 @@ Global
|
||||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x64.Build.0 = Release|Any CPU
|
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.ActiveCfg = Release|Any CPU
|
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.Build.0 = Release|Any CPU
|
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
|
@ -6677,18 +6691,6 @@ Global
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x64.Build.0 = Release|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.ActiveCfg = Release|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.Build.0 = Release|Any CPU
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
|
@ -6809,30 +6811,6 @@ Global
|
||||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x64.Build.0 = Release|Any CPU
|
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.ActiveCfg = Release|Any CPU
|
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.Build.0 = Release|Any CPU
|
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
|
@ -7071,6 +7049,150 @@ Global
|
||||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x64.Build.0 = Release|Any CPU
|
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.ActiveCfg = Release|Any CPU
|
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.Build.0 = Release|Any CPU
|
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -7771,10 +7893,8 @@ Global
|
||||||
{8550A02D-BA13-411A-AAD3-6124D33D669F} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
{8550A02D-BA13-411A-AAD3-6124D33D669F} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
||||||
{EDE77D0C-321A-49FD-95D7-56ED41242A93} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
{EDE77D0C-321A-49FD-95D7-56ED41242A93} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
||||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
|
||||||
{EE9D0952-6060-4723-B329-94A2950A6762} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
{EE9D0952-6060-4723-B329-94A2950A6762} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
||||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E} = {EE9D0952-6060-4723-B329-94A2950A6762}
|
{132D43A2-067A-4E24-A520-45B9F14DCB8E} = {EE9D0952-6060-4723-B329-94A2950A6762}
|
||||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
|
||||||
{2EC4E939-513F-44CD-A956-498966EAC929} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
{2EC4E939-513F-44CD-A956-498966EAC929} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||||
{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
||||||
{3CBC4802-E9B8-48B7-BC8C-B0AFB9EEC643} = {0ACCEDA7-339C-4B4D-8DD4-1AC271F31C04}
|
{3CBC4802-E9B8-48B7-BC8C-B0AFB9EEC643} = {0ACCEDA7-339C-4B4D-8DD4-1AC271F31C04}
|
||||||
|
|
@ -7788,8 +7908,6 @@ Global
|
||||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
{83371889-9A3E-4D16-AE77-EB4F83BC6374} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||||
{525EBCB4-A870-470B-BC90-845306C337D1} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
{525EBCB4-A870-470B-BC90-845306C337D1} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
{175E5CD8-92D4-46BB-882E-3A930D3302D4} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
|
||||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
|
||||||
{6126DCE4-9692-4EE2-B240-C65743572995} = {0508E463-0269-40C9-B5C2-3B600FB2A28B}
|
{6126DCE4-9692-4EE2-B240-C65743572995} = {0508E463-0269-40C9-B5C2-3B600FB2A28B}
|
||||||
{46FB7E93-1294-4068-B80A-D4864F78277A} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
{46FB7E93-1294-4068-B80A-D4864F78277A} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
||||||
{25FA84DB-EEA7-4068-8E2D-F3D48B281C16} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
{25FA84DB-EEA7-4068-8E2D-F3D48B281C16} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
||||||
|
|
@ -7814,6 +7932,23 @@ Global
|
||||||
{7F87406C-A3C8-4139-A68D-E4C344294A67} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
{7F87406C-A3C8-4139-A68D-E4C344294A67} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||||
{1533E271-F61B-441B-8B74-59FB61DF0552} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
{1533E271-F61B-441B-8B74-59FB61DF0552} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||||
{7E268085-1046-4362-80CB-2977FF826DCA} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
{7E268085-1046-4362-80CB-2977FF826DCA} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||||
|
{A5CE25E9-89E1-4F2C-9B89-0C161707E700} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||||
|
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||||
|
{7D2B0799-A634-42AC-AE77-5D167BA51389} = {562D5067-8CD8-4F19-BCBB-873204932C61}
|
||||||
|
{9788C76F-658B-4441-88F8-22C6B86FAD27} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{1970D5CD-D9A4-4673-A297-179BB04199F4} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{A40350FE-4334-4007-B1C3-6BEB1B070309} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{FE5290C7-45DA-46F8-BD74-698E7A161DD6} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||||
|
{C1E7F837-6988-43E2-9E1C-7302DB484F99} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
|
||||||
|
{2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E} = {C1E7F837-6988-43E2-9E1C-7302DB484F99}
|
||||||
|
{7CB09412-C9B0-47E8-A8C3-311AA4CFDE04} = {C1E7F837-6988-43E2-9E1C-7302DB484F99}
|
||||||
|
{22D7D74B-565D-4047-97B4-F149B1A13350} = {2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}
|
||||||
|
{B06040BC-DA28-4923-8CAC-20EB517D471B} = {22D7D74B-565D-4047-97B4-F149B1A13350}
|
||||||
|
{55CACC1F-FE96-47C8-8073-91F4CAA55C75} = {2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}
|
||||||
|
{7509AA1E-3093-4BEE-984F-E11579E98A11} = {7CB09412-C9B0-47E8-A8C3-311AA4CFDE04}
|
||||||
|
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E} = {16898702-3E33-41C1-B8D8-4CE3F1D46BD9}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
|
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
|
||||||
|
|
|
||||||
|
|
@ -268,3 +268,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,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
License notice for BedrockFramework
|
||||||
|
===================================
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 David Fowler
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ and are generated based on the last package release.
|
||||||
<LatestPackageReference Include="System.ComponentModel.Annotations" />
|
<LatestPackageReference Include="System.ComponentModel.Annotations" />
|
||||||
<LatestPackageReference Include="System.Diagnostics.DiagnosticSource" />
|
<LatestPackageReference Include="System.Diagnostics.DiagnosticSource" />
|
||||||
<LatestPackageReference Include="System.Diagnostics.EventLog" />
|
<LatestPackageReference Include="System.Diagnostics.EventLog" />
|
||||||
|
<LatestPackageReference Include="System.DirectoryServices.Protocols" />
|
||||||
<LatestPackageReference Include="System.Drawing.Common" />
|
<LatestPackageReference Include="System.Drawing.Common" />
|
||||||
<LatestPackageReference Include="System.IO.Pipelines" />
|
<LatestPackageReference Include="System.IO.Pipelines" />
|
||||||
<LatestPackageReference Include="System.Net.Http" />
|
<LatestPackageReference Include="System.Net.Http" />
|
||||||
|
|
@ -107,6 +108,7 @@ and are generated based on the last package release.
|
||||||
<LatestPackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
|
<LatestPackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
|
||||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" />
|
<LatestPackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" />
|
||||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" />
|
<LatestPackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" />
|
||||||
|
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Design" />
|
||||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
||||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||||
|
|
|
||||||
|
|
@ -13,305 +13,313 @@
|
||||||
<Uri>https://github.com/dotnet/blazor</Uri>
|
<Uri>https://github.com/dotnet/blazor</Uri>
|
||||||
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
|
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20417.2">
|
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="5.0.0-rc.1.20425.4">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Drawing.Common" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.IO.Pipelines" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.DirectoryServices.Protocols" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Net.Http.Json" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Drawing.Common" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.IO.Pipelines" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Net.Http.Json" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Resources.Extensions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
|
</Dependency>
|
||||||
|
<Dependency Name="System.Resources.Extensions" Version="5.0.0-rc.1.20425.1">
|
||||||
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
|
</Dependency>
|
||||||
|
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-rc.1.20425.1">
|
||||||
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||||
<Dependency Name="System.Security.AccessControl" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.AccessControl" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Security.Permissions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.Permissions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Text.Json" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Text.Json" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Threading.Channels" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Threading.Channels" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="System.Windows.Extensions" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="System.Windows.Extensions" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<!--
|
<!--
|
||||||
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
|
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
|
||||||
All Runtime.$rid packages should have the same version.
|
All Runtime.$rid packages should have the same version.
|
||||||
-->
|
-->
|
||||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
</ProductDependencies>
|
</ProductDependencies>
|
||||||
<ToolsetDependencies>
|
<ToolsetDependencies>
|
||||||
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-rc.1.20416.7">
|
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-rc.1.20425.1">
|
||||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20411.8">
|
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20419.21">
|
||||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||||
<Sha>ecec08a0eebbd92bb9538e351d475582551d9092</Sha>
|
<Sha>56a95cc477558c1ccdf16d7abe962849ea970ba4</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20411.8">
|
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20419.21">
|
||||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||||
<Sha>ecec08a0eebbd92bb9538e351d475582551d9092</Sha>
|
<Sha>56a95cc477558c1ccdf16d7abe962849ea970ba4</Sha>
|
||||||
</Dependency>
|
</Dependency>
|
||||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-2.20407.3">
|
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-2.20407.3">
|
||||||
<Uri>https://github.com/dotnet/roslyn</Uri>
|
<Uri>https://github.com/dotnet/roslyn</Uri>
|
||||||
|
|
|
||||||
|
|
@ -64,82 +64,84 @@
|
||||||
<!-- Packages from dotnet/roslyn -->
|
<!-- Packages from dotnet/roslyn -->
|
||||||
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-2.20407.3</MicrosoftNetCompilersToolsetPackageVersion>
|
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-2.20407.3</MicrosoftNetCompilersToolsetPackageVersion>
|
||||||
<!-- Packages from dotnet/runtime -->
|
<!-- Packages from dotnet/runtime -->
|
||||||
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyModelPackageVersion>
|
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||||
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppInternalPackageVersion>
|
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppInternalPackageVersion>
|
||||||
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppRefPackageVersion>
|
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppRefPackageVersion>
|
||||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||||
<MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20416.7</MicrosoftWin32RegistryPackageVersion>
|
<MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20425.1</MicrosoftWin32RegistryPackageVersion>
|
||||||
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftWin32SystemEventsPackageVersion>
|
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftWin32SystemEventsPackageVersion>
|
||||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsCachingMemoryPackageVersion>
|
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationIniPackageVersion>
|
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationPackageVersion>
|
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostingPackageVersion>
|
<MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostingPackageVersion>
|
||||||
<MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHttpPackageVersion>
|
<MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHttpPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingConsolePackageVersion>
|
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||||
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingDebugPackageVersion>
|
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingPackageVersion>
|
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||||
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsPackageVersion>
|
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsPackageVersion>
|
||||||
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsPrimitivesPackageVersion>
|
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||||
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsInternalTransportPackageVersion>
|
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsInternalTransportPackageVersion>
|
||||||
<SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20416.7</SystemComponentModelAnnotationsPackageVersion>
|
<SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20425.1</SystemComponentModelAnnotationsPackageVersion>
|
||||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20416.7</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20425.1</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||||
<SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20416.7</SystemDiagnosticsEventLogPackageVersion>
|
<SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20425.1</SystemDiagnosticsEventLogPackageVersion>
|
||||||
<SystemDrawingCommonPackageVersion>5.0.0-rc.1.20416.7</SystemDrawingCommonPackageVersion>
|
<SystemDirectoryServicesProtocolsPackageVersion>5.0.0-rc.1.20425.1</SystemDirectoryServicesProtocolsPackageVersion>
|
||||||
<SystemIOPipelinesPackageVersion>5.0.0-rc.1.20416.7</SystemIOPipelinesPackageVersion>
|
<SystemDrawingCommonPackageVersion>5.0.0-rc.1.20425.1</SystemDrawingCommonPackageVersion>
|
||||||
<SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20416.7</SystemNetHttpJsonPackageVersion>
|
<SystemIOPipelinesPackageVersion>5.0.0-rc.1.20425.1</SystemIOPipelinesPackageVersion>
|
||||||
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20416.7</SystemNetHttpWinHttpHandlerPackageVersion>
|
<SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20425.1</SystemNetHttpJsonPackageVersion>
|
||||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20416.7</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20425.1</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||||
<SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20416.7</SystemReflectionMetadataPackageVersion>
|
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20425.1</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||||
<SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20416.7</SystemResourcesExtensionsPackageVersion>
|
<SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20425.1</SystemReflectionMetadataPackageVersion>
|
||||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20416.7</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
<SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20425.1</SystemResourcesExtensionsPackageVersion>
|
||||||
|
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20425.1</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||||
<SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityAccessControlPackageVersion>
|
<SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityAccessControlPackageVersion>
|
||||||
<SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyCngPackageVersion>
|
<SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyCngPackageVersion>
|
||||||
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyPkcsPackageVersion>
|
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyPkcsPackageVersion>
|
||||||
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyXmlPackageVersion>
|
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyXmlPackageVersion>
|
||||||
<SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityPermissionsPackageVersion>
|
<SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityPermissionsPackageVersion>
|
||||||
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityPrincipalWindowsPackageVersion>
|
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityPrincipalWindowsPackageVersion>
|
||||||
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20416.7</SystemServiceProcessServiceControllerPackageVersion>
|
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20425.1</SystemServiceProcessServiceControllerPackageVersion>
|
||||||
<SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20416.7</SystemTextEncodingsWebPackageVersion>
|
<SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20425.1</SystemTextEncodingsWebPackageVersion>
|
||||||
<SystemTextJsonPackageVersion>5.0.0-rc.1.20416.7</SystemTextJsonPackageVersion>
|
<SystemTextJsonPackageVersion>5.0.0-rc.1.20425.1</SystemTextJsonPackageVersion>
|
||||||
<SystemThreadingChannelsPackageVersion>5.0.0-rc.1.20416.7</SystemThreadingChannelsPackageVersion>
|
<SystemThreadingChannelsPackageVersion>5.0.0-rc.1.20425.1</SystemThreadingChannelsPackageVersion>
|
||||||
<SystemWindowsExtensionsPackageVersion>5.0.0-rc.1.20416.7</SystemWindowsExtensionsPackageVersion>
|
<SystemWindowsExtensionsPackageVersion>5.0.0-rc.1.20425.1</SystemWindowsExtensionsPackageVersion>
|
||||||
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||||
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCorePlatformsPackageVersion>
|
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCorePlatformsPackageVersion>
|
||||||
<!-- Packages from dotnet/blazor -->
|
<!-- Packages from dotnet/blazor -->
|
||||||
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
|
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
|
||||||
<!-- Packages from dotnet/efcore -->
|
<!-- Packages from dotnet/efcore -->
|
||||||
<dotnetefPackageVersion>5.0.0-rc.1.20417.2</dotnetefPackageVersion>
|
<dotnetefPackageVersion>5.0.0-rc.1.20425.4</dotnetefPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCorePackageVersion>
|
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCorePackageVersion>
|
||||||
|
<MicrosoftEntityFrameworkCoreDesignPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreDesignPackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
|
|
@ -250,11 +252,11 @@
|
||||||
<GrpcAuthPackageVersion>2.27.0</GrpcAuthPackageVersion>
|
<GrpcAuthPackageVersion>2.27.0</GrpcAuthPackageVersion>
|
||||||
<GrpcNetClientPackageVersion>2.27.0</GrpcNetClientPackageVersion>
|
<GrpcNetClientPackageVersion>2.27.0</GrpcNetClientPackageVersion>
|
||||||
<GrpcToolsPackageVersion>2.27.0</GrpcToolsPackageVersion>
|
<GrpcToolsPackageVersion>2.27.0</GrpcToolsPackageVersion>
|
||||||
<IdentityServer4AspNetIdentityPackageVersion>3.0.0</IdentityServer4AspNetIdentityPackageVersion>
|
<IdentityServer4AspNetIdentityPackageVersion>4.0.4</IdentityServer4AspNetIdentityPackageVersion>
|
||||||
<IdentityServer4EntityFrameworkPackageVersion>3.0.0</IdentityServer4EntityFrameworkPackageVersion>
|
<IdentityServer4EntityFrameworkPackageVersion>4.0.4</IdentityServer4EntityFrameworkPackageVersion>
|
||||||
<IdentityServer4PackageVersion>3.0.0</IdentityServer4PackageVersion>
|
<IdentityServer4PackageVersion>4.0.4</IdentityServer4PackageVersion>
|
||||||
<IdentityServer4StoragePackageVersion>3.0.0</IdentityServer4StoragePackageVersion>
|
<IdentityServer4StoragePackageVersion>4.0.4</IdentityServer4StoragePackageVersion>
|
||||||
<IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0</IdentityServer4EntityFrameworkStoragePackageVersion>
|
<IdentityServer4EntityFrameworkStoragePackageVersion>4.0.4</IdentityServer4EntityFrameworkStoragePackageVersion>
|
||||||
<MessagePackPackageVersion>2.1.90</MessagePackPackageVersion>
|
<MessagePackPackageVersion>2.1.90</MessagePackPackageVersion>
|
||||||
<MicrosoftIdentityWebPackageVersion>0.2.1-preview</MicrosoftIdentityWebPackageVersion>
|
<MicrosoftIdentityWebPackageVersion>0.2.1-preview</MicrosoftIdentityWebPackageVersion>
|
||||||
<MicrosoftIdentityWebUIPackageVersion>0.2.1-preview</MicrosoftIdentityWebUIPackageVersion>
|
<MicrosoftIdentityWebUIPackageVersion>0.2.1-preview</MicrosoftIdentityWebUIPackageVersion>
|
||||||
|
|
@ -273,6 +275,7 @@
|
||||||
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
|
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
|
||||||
<StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion>
|
<StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion>
|
||||||
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
|
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
|
||||||
|
<SwashbuckleAspNetCorePackageVersion>5.5.1</SwashbuckleAspNetCorePackageVersion>
|
||||||
<XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion>
|
<XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion>
|
||||||
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
||||||
<XunitVersion>2.4.1</XunitVersion>
|
<XunitVersion>2.4.1</XunitVersion>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ if(TARGET_ARCH_NAME STREQUAL "armel")
|
||||||
endif()
|
endif()
|
||||||
elseif(TARGET_ARCH_NAME STREQUAL "arm")
|
elseif(TARGET_ARCH_NAME STREQUAL "arm")
|
||||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||||
if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
|
if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv7-alpine-linux-musleabihf)
|
||||||
|
set(TOOLCHAIN "armv7-alpine-linux-musleabihf")
|
||||||
|
elseif(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
|
||||||
set(TOOLCHAIN "armv6-alpine-linux-musleabihf")
|
set(TOOLCHAIN "armv6-alpine-linux-musleabihf")
|
||||||
else()
|
else()
|
||||||
set(TOOLCHAIN "arm-linux-gnueabihf")
|
set(TOOLCHAIN "arm-linux-gnueabihf")
|
||||||
|
|
|
||||||
|
|
@ -199,14 +199,15 @@ if [[ "$mono_dotnet" != "" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$wasm_runtime_loc" != "" ]]; then
|
if [[ "$wasm_runtime_loc" != "" ]]; then
|
||||||
configurations="CompilationMode=wasm;RunKind=micro"
|
configurations="CompilationMode=wasm RunKind=micro"
|
||||||
|
extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoInterpreter NoWASM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$monointerpreter" == "true" ]]; then
|
if [[ "$monointerpreter" == "true" ]]; then
|
||||||
extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoInterpreter"
|
extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoInterpreter"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs \"$configurations\" --architecture $architecture"
|
common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture"
|
||||||
setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments"
|
setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)][int] $BuildId,
|
[Parameter(Mandatory=$true)][int] $BuildId,
|
||||||
|
[Parameter(Mandatory=$true)][int] $PublishingInfraVersion,
|
||||||
[Parameter(Mandatory=$true)][string] $AzdoToken,
|
[Parameter(Mandatory=$true)][string] $AzdoToken,
|
||||||
[Parameter(Mandatory=$true)][string] $MaestroToken,
|
[Parameter(Mandatory=$true)][string] $MaestroToken,
|
||||||
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com',
|
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com',
|
||||||
[Parameter(Mandatory=$true)][string] $WaitPublishingFinish,
|
[Parameter(Mandatory=$true)][string] $WaitPublishingFinish,
|
||||||
[Parameter(Mandatory=$true)][string] $EnableSourceLinkValidation,
|
[Parameter(Mandatory=$false)][string] $EnableSourceLinkValidation,
|
||||||
[Parameter(Mandatory=$true)][string] $EnableSigningValidation,
|
[Parameter(Mandatory=$false)][string] $EnableSigningValidation,
|
||||||
[Parameter(Mandatory=$true)][string] $EnableNugetValidation,
|
[Parameter(Mandatory=$false)][string] $EnableNugetValidation,
|
||||||
[Parameter(Mandatory=$true)][string] $PublishInstallersAndChecksums,
|
[Parameter(Mandatory=$true)][string] $PublishInstallersAndChecksums,
|
||||||
[Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters,
|
[Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters,
|
||||||
[Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters
|
[Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters
|
||||||
|
|
@ -14,7 +15,8 @@ param(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
. $PSScriptRoot\post-build-utils.ps1
|
. $PSScriptRoot\post-build-utils.ps1
|
||||||
. $PSScriptRoot\..\darc-init.ps1
|
# Hard coding darc version till the next arcade-services roll out, cos this version has required API changes for darc add-build-to-channel
|
||||||
|
. $PSScriptRoot\..\darc-init.ps1 -darcVersion "1.1.0-beta.20418.1"
|
||||||
|
|
||||||
$optionalParams = [System.Collections.ArrayList]::new()
|
$optionalParams = [System.Collections.ArrayList]::new()
|
||||||
|
|
||||||
|
|
@ -49,12 +51,13 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
& darc add-build-to-channel `
|
& darc add-build-to-channel `
|
||||||
--id $buildId `
|
--id $buildId `
|
||||||
--default-channels `
|
--publishing-infra-version $PublishingInfraVersion `
|
||||||
--source-branch master `
|
--default-channels `
|
||||||
--azdev-pat $AzdoToken `
|
--source-branch master `
|
||||||
--bar-uri $MaestroApiEndPoint `
|
--azdev-pat $AzdoToken `
|
||||||
--password $MaestroToken `
|
--bar-uri $MaestroApiEndPoint `
|
||||||
|
--password $MaestroToken `
|
||||||
@optionalParams
|
@optionalParams
|
||||||
|
|
||||||
if ($LastExitCode -ne 0) {
|
if ($LastExitCode -ne 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ''
|
||||||
|
PromoteToChannelIds: ''
|
||||||
artifactsPublishingAdditionalParameters: ''
|
artifactsPublishingAdditionalParameters: ''
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- Validate
|
- Validate
|
||||||
|
|
@ -19,6 +21,9 @@ stages:
|
||||||
displayName: ${{ parameters.channelName }} Publishing
|
displayName: ${{ parameters.channelName }} Publishing
|
||||||
jobs:
|
jobs:
|
||||||
- template: ../setup-maestro-vars.yml
|
- template: ../setup-maestro-vars.yml
|
||||||
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
|
|
||||||
- job: publish_symbols
|
- job: publish_symbols
|
||||||
displayName: Symbol Publishing
|
displayName: Symbol Publishing
|
||||||
|
|
@ -138,6 +143,7 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
filePath: eng\common\sdk-task.ps1
|
filePath: eng\common\sdk-task.ps1
|
||||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||||
|
/p:PublishingInfraVersion=2
|
||||||
/p:IsStableBuild=$(IsStableBuild)
|
/p:IsStableBuild=$(IsStableBuild)
|
||||||
/p:IsInternalBuild=$(IsInternalBuild)
|
/p:IsInternalBuild=$(IsInternalBuild)
|
||||||
/p:RepositoryName=$(Build.Repository.Name)
|
/p:RepositoryName=$(Build.Repository.Name)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ''
|
||||||
|
PromoteToChannelIds: ''
|
||||||
artifactsPublishingAdditionalParameters: ''
|
artifactsPublishingAdditionalParameters: ''
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- Validate
|
- Validate
|
||||||
|
|
@ -21,6 +23,9 @@ stages:
|
||||||
displayName: ${{ parameters.channelName }} Publishing
|
displayName: ${{ parameters.channelName }} Publishing
|
||||||
jobs:
|
jobs:
|
||||||
- template: ../setup-maestro-vars.yml
|
- template: ../setup-maestro-vars.yml
|
||||||
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
|
|
||||||
- job: publish_symbols
|
- job: publish_symbols
|
||||||
displayName: Symbol Publishing
|
displayName: Symbol Publishing
|
||||||
|
|
@ -137,6 +142,7 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
filePath: eng\common\sdk-task.ps1
|
filePath: eng\common\sdk-task.ps1
|
||||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||||
|
/p:PublishingInfraVersion=2
|
||||||
/p:ArtifactsCategory=$(ArtifactsCategory)
|
/p:ArtifactsCategory=$(ArtifactsCategory)
|
||||||
/p:IsStableBuild=$(IsStableBuild)
|
/p:IsStableBuild=$(IsStableBuild)
|
||||||
/p:IsInternalBuild=$(IsInternalBuild)
|
/p:IsInternalBuild=$(IsInternalBuild)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
parameters:
|
parameters:
|
||||||
|
# Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST.
|
||||||
|
# Publishing V2 accepts optionally outlining the publishing stages - default is inline.
|
||||||
|
# Publishing V3 DOES NOT accept inlining the publishing stages.
|
||||||
|
publishingInfraVersion: 2
|
||||||
# When set to true the publishing templates from the repo will be used
|
# When set to true the publishing templates from the repo will be used
|
||||||
# otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline
|
# otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline
|
||||||
inline: true
|
inline: true
|
||||||
|
|
||||||
# Only used if inline==false. When set to true will stall the current build until
|
# Only used if inline==false. When set to true will stall the current build until
|
||||||
# the Promotion Pipeline build finishes. Otherwise, the current build continue
|
# the Promotion Pipeline build finishes. Otherwise, the current build will continue
|
||||||
# execution concurrently with the promotion build.
|
# execution concurrently with the promotion build.
|
||||||
waitPublishingFinish: true
|
waitPublishingFinish: true
|
||||||
|
|
||||||
|
BARBuildId: ''
|
||||||
|
PromoteToChannelIds: ''
|
||||||
|
|
||||||
enableSourceLinkValidation: false
|
enableSourceLinkValidation: false
|
||||||
enableSigningValidation: true
|
enableSigningValidation: true
|
||||||
enableSymbolValidation: false
|
enableSymbolValidation: false
|
||||||
|
|
@ -39,6 +46,7 @@ parameters:
|
||||||
NetEngLatestChannelId: 2
|
NetEngLatestChannelId: 2
|
||||||
NetEngValidationChannelId: 9
|
NetEngValidationChannelId: 9
|
||||||
NetDev5ChannelId: 131
|
NetDev5ChannelId: 131
|
||||||
|
NetDev6ChannelId: 1296
|
||||||
GeneralTestingChannelId: 529
|
GeneralTestingChannelId: 529
|
||||||
NETCoreToolingDevChannelId: 548
|
NETCoreToolingDevChannelId: 548
|
||||||
NETCoreToolingReleaseChannelId: 549
|
NETCoreToolingReleaseChannelId: 549
|
||||||
|
|
@ -46,7 +54,6 @@ parameters:
|
||||||
NETCoreExperimentalChannelId: 562
|
NETCoreExperimentalChannelId: 562
|
||||||
NetEngServicesIntChannelId: 678
|
NetEngServicesIntChannelId: 678
|
||||||
NetEngServicesProdChannelId: 679
|
NetEngServicesProdChannelId: 679
|
||||||
Net5Preview7ChannelId: 1065
|
|
||||||
Net5Preview8ChannelId: 1155
|
Net5Preview8ChannelId: 1155
|
||||||
Net5RC1ChannelId: 1157
|
Net5RC1ChannelId: 1157
|
||||||
NetCoreSDK313xxChannelId: 759
|
NetCoreSDK313xxChannelId: 759
|
||||||
|
|
@ -59,14 +66,183 @@ parameters:
|
||||||
VSMasterChannelId: 1012
|
VSMasterChannelId: 1012
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- ${{ if ne(parameters.inline, 'true') }}:
|
- stage: Validate
|
||||||
|
dependsOn: ${{ parameters.validateDependsOn }}
|
||||||
|
displayName: Validate Build Assets
|
||||||
|
variables:
|
||||||
|
- template: common-variables.yml
|
||||||
|
jobs:
|
||||||
|
- template: setup-maestro-vars.yml
|
||||||
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
|
|
||||||
|
- job:
|
||||||
|
displayName: Post-build Checks
|
||||||
|
dependsOn: setupMaestroVars
|
||||||
|
variables:
|
||||||
|
- name: TargetChannels
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ]
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
steps:
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Maestro Channels Consistency
|
||||||
|
inputs:
|
||||||
|
filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
|
||||||
|
arguments: -PromoteToChannels "$(TargetChannels)"
|
||||||
|
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview8ChannelId}},${{parameters.Net5RC1ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}}
|
||||||
|
|
||||||
|
- job:
|
||||||
|
displayName: NuGet Validation
|
||||||
|
dependsOn: setupMaestroVars
|
||||||
|
condition: eq( ${{ parameters.enableNugetValidation }}, 'true')
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
variables:
|
||||||
|
- name: AzDOProjectName
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||||
|
- name: AzDOPipelineId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||||
|
- name: AzDOBuildId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||||
|
steps:
|
||||||
|
- task: DownloadBuildArtifacts@0
|
||||||
|
displayName: Download Package Artifacts
|
||||||
|
inputs:
|
||||||
|
buildType: specific
|
||||||
|
buildVersionToDownload: specific
|
||||||
|
project: $(AzDOProjectName)
|
||||||
|
pipeline: $(AzDOPipelineId)
|
||||||
|
buildId: $(AzDOBuildId)
|
||||||
|
artifactName: PackageArtifacts
|
||||||
|
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Validate
|
||||||
|
inputs:
|
||||||
|
filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
|
||||||
|
arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
|
||||||
|
-ToolDestinationPath $(Agent.BuildDirectory)/Extract/
|
||||||
|
|
||||||
|
- job:
|
||||||
|
displayName: Signing Validation
|
||||||
|
dependsOn: setupMaestroVars
|
||||||
|
condition: eq( ${{ parameters.enableSigningValidation }}, 'true')
|
||||||
|
variables:
|
||||||
|
- template: common-variables.yml
|
||||||
|
- name: AzDOProjectName
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||||
|
- name: AzDOPipelineId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||||
|
- name: AzDOBuildId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
steps:
|
||||||
|
- ${{ if eq(parameters.useBuildManifest, true) }}:
|
||||||
|
- task: DownloadBuildArtifacts@0
|
||||||
|
displayName: Download build manifest
|
||||||
|
inputs:
|
||||||
|
buildType: specific
|
||||||
|
buildVersionToDownload: specific
|
||||||
|
project: $(AzDOProjectName)
|
||||||
|
pipeline: $(AzDOPipelineId)
|
||||||
|
buildId: $(AzDOBuildId)
|
||||||
|
artifactName: BuildManifests
|
||||||
|
- task: DownloadBuildArtifacts@0
|
||||||
|
displayName: Download Package Artifacts
|
||||||
|
inputs:
|
||||||
|
buildType: specific
|
||||||
|
buildVersionToDownload: specific
|
||||||
|
project: $(AzDOProjectName)
|
||||||
|
pipeline: $(AzDOPipelineId)
|
||||||
|
buildId: $(AzDOBuildId)
|
||||||
|
artifactName: PackageArtifacts
|
||||||
|
|
||||||
|
# This is necessary whenever we want to publish/restore to an AzDO private feed
|
||||||
|
# Since sdk-task.ps1 tries to restore packages we need to do this authentication here
|
||||||
|
# otherwise it'll complain about accessing a private feed.
|
||||||
|
- task: NuGetAuthenticate@0
|
||||||
|
displayName: 'Authenticate to AzDO Feeds'
|
||||||
|
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Enable cross-org publishing
|
||||||
|
inputs:
|
||||||
|
filePath: eng\common\enable-cross-org-publishing.ps1
|
||||||
|
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
|
||||||
|
|
||||||
|
# Signing validation will optionally work with the buildmanifest file which is downloaded from
|
||||||
|
# Azure DevOps above.
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Validate
|
||||||
|
inputs:
|
||||||
|
filePath: eng\common\sdk-task.ps1
|
||||||
|
arguments: -task SigningValidation -restore -msbuildEngine vs
|
||||||
|
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts'
|
||||||
|
/p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt'
|
||||||
|
${{ parameters.signingValidationAdditionalParameters }}
|
||||||
|
|
||||||
|
- template: ../steps/publish-logs.yml
|
||||||
|
parameters:
|
||||||
|
StageLabel: 'Validation'
|
||||||
|
JobLabel: 'Signing'
|
||||||
|
|
||||||
|
- job:
|
||||||
|
displayName: SourceLink Validation
|
||||||
|
dependsOn: setupMaestroVars
|
||||||
|
condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true')
|
||||||
|
variables:
|
||||||
|
- template: common-variables.yml
|
||||||
|
- name: AzDOProjectName
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||||
|
- name: AzDOPipelineId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||||
|
- name: AzDOBuildId
|
||||||
|
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
steps:
|
||||||
|
- task: DownloadBuildArtifacts@0
|
||||||
|
displayName: Download Blob Artifacts
|
||||||
|
inputs:
|
||||||
|
buildType: specific
|
||||||
|
buildVersionToDownload: specific
|
||||||
|
project: $(AzDOProjectName)
|
||||||
|
pipeline: $(AzDOPipelineId)
|
||||||
|
buildId: $(AzDOBuildId)
|
||||||
|
artifactName: BlobArtifacts
|
||||||
|
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Validate
|
||||||
|
inputs:
|
||||||
|
filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
|
||||||
|
arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
||||||
|
-ExtractPath $(Agent.BuildDirectory)/Extract/
|
||||||
|
-GHRepoName $(Build.Repository.Name)
|
||||||
|
-GHCommit $(Build.SourceVersion)
|
||||||
|
-SourcelinkCliVersion $(SourceLinkCLIVersion)
|
||||||
|
continueOnError: true
|
||||||
|
|
||||||
|
- template: /eng/common/templates/job/execute-sdl.yml
|
||||||
|
parameters:
|
||||||
|
enable: ${{ parameters.SDLValidationParameters.enable }}
|
||||||
|
dependsOn: setupMaestroVars
|
||||||
|
additionalParameters: ${{ parameters.SDLValidationParameters.params }}
|
||||||
|
continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }}
|
||||||
|
artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }}
|
||||||
|
downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }}
|
||||||
|
|
||||||
|
- ${{ if or(ge(parameters.publishingInfraVersion, 3), eq(parameters.inline, 'false')) }}:
|
||||||
- stage: publish_using_darc
|
- stage: publish_using_darc
|
||||||
dependsOn: ${{ parameters.validateDependsOn }}
|
dependsOn: Validate
|
||||||
displayName: Publish using Darc
|
displayName: Publish using Darc
|
||||||
variables:
|
variables:
|
||||||
- template: common-variables.yml
|
- template: common-variables.yml
|
||||||
jobs:
|
jobs:
|
||||||
- template: setup-maestro-vars.yml
|
- template: setup-maestro-vars.yml
|
||||||
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
displayName: Publish Using Darc
|
displayName: Publish Using Darc
|
||||||
|
|
@ -82,182 +258,17 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
|
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
|
||||||
arguments: -BuildId $(BARBuildId)
|
arguments: -BuildId $(BARBuildId)
|
||||||
|
-PublishingInfraVersion ${{ parameters.PublishingInfraVersion }}
|
||||||
-AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
|
-AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
|
||||||
-MaestroToken '$(MaestroApiAccessToken)'
|
-MaestroToken '$(MaestroApiAccessToken)'
|
||||||
-WaitPublishingFinish ${{ parameters.waitPublishingFinish }}
|
-WaitPublishingFinish ${{ parameters.waitPublishingFinish }}
|
||||||
-EnableSourceLinkValidation ${{ parameters.enableSourceLinkValidation }}
|
|
||||||
-EnableSigningValidation ${{ parameters.enableSourceLinkValidation }}
|
|
||||||
-EnableNugetValidation ${{ parameters.enableSourceLinkValidation }}
|
|
||||||
-PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }}
|
-PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }}
|
||||||
-ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}'
|
|
||||||
-SigningValidationAdditionalParameters '${{ parameters.signingValidationAdditionalParameters }}'
|
|
||||||
|
|
||||||
- ${{ if eq(parameters.inline, 'true') }}:
|
|
||||||
- stage: Validate
|
|
||||||
dependsOn: ${{ parameters.validateDependsOn }}
|
|
||||||
displayName: Validate Build Assets
|
|
||||||
variables:
|
|
||||||
- template: common-variables.yml
|
|
||||||
jobs:
|
|
||||||
- template: setup-maestro-vars.yml
|
|
||||||
|
|
||||||
- job:
|
|
||||||
displayName: Post-build Checks
|
|
||||||
dependsOn: setupMaestroVars
|
|
||||||
variables:
|
|
||||||
- name: TargetChannels
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ]
|
|
||||||
pool:
|
|
||||||
vmImage: 'windows-2019'
|
|
||||||
steps:
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: Maestro Channels Consistency
|
|
||||||
inputs:
|
|
||||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
|
|
||||||
arguments: -PromoteToChannels "$(TargetChannels)"
|
|
||||||
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview7ChannelId}},${{parameters.Net5Preview8ChannelId}},${{parameters.Net5RC1ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}}
|
|
||||||
|
|
||||||
- job:
|
|
||||||
displayName: NuGet Validation
|
|
||||||
dependsOn: setupMaestroVars
|
|
||||||
condition: eq( ${{ parameters.enableNugetValidation }}, 'true')
|
|
||||||
pool:
|
|
||||||
vmImage: 'windows-2019'
|
|
||||||
variables:
|
|
||||||
- name: AzDOProjectName
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
|
||||||
- name: AzDOPipelineId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
|
||||||
- name: AzDOBuildId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
|
||||||
steps:
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: Download Package Artifacts
|
|
||||||
inputs:
|
|
||||||
buildType: specific
|
|
||||||
buildVersionToDownload: specific
|
|
||||||
project: $(AzDOProjectName)
|
|
||||||
pipeline: $(AzDOPipelineId)
|
|
||||||
buildId: $(AzDOBuildId)
|
|
||||||
artifactName: PackageArtifacts
|
|
||||||
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: Validate
|
|
||||||
inputs:
|
|
||||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
|
|
||||||
arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
|
|
||||||
-ToolDestinationPath $(Agent.BuildDirectory)/Extract/
|
|
||||||
|
|
||||||
- job:
|
|
||||||
displayName: Signing Validation
|
|
||||||
dependsOn: setupMaestroVars
|
|
||||||
condition: eq( ${{ parameters.enableSigningValidation }}, 'true')
|
|
||||||
variables:
|
|
||||||
- template: common-variables.yml
|
|
||||||
- name: AzDOProjectName
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
|
||||||
- name: AzDOPipelineId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
|
||||||
- name: AzDOBuildId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
|
||||||
pool:
|
|
||||||
vmImage: 'windows-2019'
|
|
||||||
steps:
|
|
||||||
- ${{ if eq(parameters.useBuildManifest, true) }}:
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: Download build manifest
|
|
||||||
inputs:
|
|
||||||
buildType: specific
|
|
||||||
buildVersionToDownload: specific
|
|
||||||
project: $(AzDOProjectName)
|
|
||||||
pipeline: $(AzDOPipelineId)
|
|
||||||
buildId: $(AzDOBuildId)
|
|
||||||
artifactName: BuildManifests
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: Download Package Artifacts
|
|
||||||
inputs:
|
|
||||||
buildType: specific
|
|
||||||
buildVersionToDownload: specific
|
|
||||||
project: $(AzDOProjectName)
|
|
||||||
pipeline: $(AzDOPipelineId)
|
|
||||||
buildId: $(AzDOBuildId)
|
|
||||||
artifactName: PackageArtifacts
|
|
||||||
|
|
||||||
# This is necessary whenever we want to publish/restore to an AzDO private feed
|
|
||||||
# Since sdk-task.ps1 tries to restore packages we need to do this authentication here
|
|
||||||
# otherwise it'll complain about accessing a private feed.
|
|
||||||
- task: NuGetAuthenticate@0
|
|
||||||
displayName: 'Authenticate to AzDO Feeds'
|
|
||||||
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: Enable cross-org publishing
|
|
||||||
inputs:
|
|
||||||
filePath: eng\common\enable-cross-org-publishing.ps1
|
|
||||||
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
|
|
||||||
|
|
||||||
# Signing validation will optionally work with the buildmanifest file which is downloaded from
|
|
||||||
# Azure DevOps above.
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: Validate
|
|
||||||
inputs:
|
|
||||||
filePath: eng\common\sdk-task.ps1
|
|
||||||
arguments: -task SigningValidation -restore -msbuildEngine vs
|
|
||||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts'
|
|
||||||
/p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt'
|
|
||||||
${{ parameters.signingValidationAdditionalParameters }}
|
|
||||||
|
|
||||||
- template: ../steps/publish-logs.yml
|
|
||||||
parameters:
|
|
||||||
StageLabel: 'Validation'
|
|
||||||
JobLabel: 'Signing'
|
|
||||||
|
|
||||||
- job:
|
|
||||||
displayName: SourceLink Validation
|
|
||||||
dependsOn: setupMaestroVars
|
|
||||||
condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true')
|
|
||||||
variables:
|
|
||||||
- template: common-variables.yml
|
|
||||||
- name: AzDOProjectName
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
|
||||||
- name: AzDOPipelineId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
|
||||||
- name: AzDOBuildId
|
|
||||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
|
||||||
pool:
|
|
||||||
vmImage: 'windows-2019'
|
|
||||||
steps:
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: Download Blob Artifacts
|
|
||||||
inputs:
|
|
||||||
buildType: specific
|
|
||||||
buildVersionToDownload: specific
|
|
||||||
project: $(AzDOProjectName)
|
|
||||||
pipeline: $(AzDOPipelineId)
|
|
||||||
buildId: $(AzDOBuildId)
|
|
||||||
artifactName: BlobArtifacts
|
|
||||||
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: Validate
|
|
||||||
inputs:
|
|
||||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
|
|
||||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
|
||||||
-ExtractPath $(Agent.BuildDirectory)/Extract/
|
|
||||||
-GHRepoName $(Build.Repository.Name)
|
|
||||||
-GHCommit $(Build.SourceVersion)
|
|
||||||
-SourcelinkCliVersion $(SourceLinkCLIVersion)
|
|
||||||
continueOnError: true
|
|
||||||
|
|
||||||
- template: /eng/common/templates/job/execute-sdl.yml
|
|
||||||
parameters:
|
|
||||||
enable: ${{ parameters.SDLValidationParameters.enable }}
|
|
||||||
dependsOn: setupMaestroVars
|
|
||||||
additionalParameters: ${{ parameters.SDLValidationParameters.params }}
|
|
||||||
continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }}
|
|
||||||
artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }}
|
|
||||||
downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }}
|
|
||||||
|
|
||||||
|
- ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}:
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -272,20 +283,24 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
|
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
|
||||||
stageName: 'Net5_Preview7_Publish'
|
stageName: 'NetCore_Dev6_Publish'
|
||||||
channelName: '.NET 5 Preview 7'
|
channelName: '.NET 6 Dev'
|
||||||
akaMSChannelName: 'net5/preview7'
|
akaMSChannelName: 'net6/dev'
|
||||||
channelId: ${{ parameters.Net5Preview7ChannelId }}
|
channelId: ${{ parameters.NetDev6ChannelId }}
|
||||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
|
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json'
|
||||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
|
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json'
|
||||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
|
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json'
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -298,8 +313,10 @@ stages:
|
||||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json'
|
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json'
|
||||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-symbols/nuget/v3/index.json'
|
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-symbols/nuget/v3/index.json'
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -308,12 +325,14 @@ stages:
|
||||||
channelName: '.NET 5 RC 1'
|
channelName: '.NET 5 RC 1'
|
||||||
akaMSChannelName: 'net5/rc1'
|
akaMSChannelName: 'net5/rc1'
|
||||||
channelId: ${{ parameters.Net5RC1ChannelId }}
|
channelId: ${{ parameters.Net5RC1ChannelId }}
|
||||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-transport/nuget/v3/index.json'
|
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
|
||||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json'
|
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
|
||||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-symbols/nuget/v3/index.json'
|
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -328,6 +347,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -342,6 +363,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -356,6 +379,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -369,6 +394,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -382,6 +409,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -395,6 +424,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -408,6 +439,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -421,6 +454,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -434,6 +469,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -447,6 +484,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -460,6 +499,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -473,6 +514,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -486,6 +529,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -499,6 +544,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -512,6 +559,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
@ -525,6 +574,8 @@ stages:
|
||||||
|
|
||||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||||
dependsOn: ${{ parameters.publishDependsOn }}
|
dependsOn: ${{ parameters.publishDependsOn }}
|
||||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,23 @@
|
||||||
|
parameters:
|
||||||
|
BARBuildId: ''
|
||||||
|
PromoteToChannelIds: ''
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: setupMaestroVars
|
- job: setupMaestroVars
|
||||||
displayName: Setup Maestro Vars
|
displayName: Setup Maestro Vars
|
||||||
variables:
|
variables:
|
||||||
- template: common-variables.yml
|
- template: common-variables.yml
|
||||||
- name: BuildId
|
|
||||||
value: $[ coalesce(variables.BARBuildId, 0) ]
|
|
||||||
- name: PromoteToMaestroChannels
|
|
||||||
value: $[ coalesce(variables.PromoteToChannelIds, 0) ]
|
|
||||||
- name: PromoteToMaestroChannel
|
|
||||||
value: $[ coalesce(variables.PromoteToMaestroChannelId, 0) ]
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'windows-2019'
|
vmImage: 'windows-2019'
|
||||||
steps:
|
steps:
|
||||||
- checkout: none
|
- checkout: none
|
||||||
|
|
||||||
- task: DownloadBuildArtifacts@0
|
- ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}:
|
||||||
displayName: Download Release Configs
|
- task: DownloadBuildArtifacts@0
|
||||||
condition: and(eq(variables.PromoteToMaestroChannels, 0), eq(variables.PromoteToMaestroChannel, 0))
|
displayName: Download Release Configs
|
||||||
inputs:
|
inputs:
|
||||||
buildType: current
|
buildType: current
|
||||||
artifactName: ReleaseConfigs
|
artifactName: ReleaseConfigs
|
||||||
|
|
||||||
- task: PowerShell@2
|
- task: PowerShell@2
|
||||||
name: setReleaseVars
|
name: setReleaseVars
|
||||||
|
|
@ -28,7 +26,7 @@ jobs:
|
||||||
targetType: inline
|
targetType: inline
|
||||||
script: |
|
script: |
|
||||||
try {
|
try {
|
||||||
if ($Env:PromoteToMaestroChannels -eq 0 -and $Env:PromoteToMaestroChannel -eq 0) {
|
if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') {
|
||||||
$Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt
|
$Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt
|
||||||
|
|
||||||
$BarId = $Content | Select -Index 0
|
$BarId = $Content | Select -Index 0
|
||||||
|
|
@ -51,7 +49,7 @@ jobs:
|
||||||
$BarId = $Env:BARBuildId
|
$BarId = $Env:BARBuildId
|
||||||
$Channels = $Env:PromoteToMaestroChannels -split ","
|
$Channels = $Env:PromoteToMaestroChannels -split ","
|
||||||
$Channels = $Channels -join "]["
|
$Channels = $Channels -join "]["
|
||||||
$Channels = "[$Channels][$Env:PromoteToMaestroChannel]"
|
$Channels = "[$Channels]"
|
||||||
|
|
||||||
$IsStableBuild = $buildInfo.stable
|
$IsStableBuild = $buildInfo.stable
|
||||||
$AzureDevOpsProject = $buildInfo.azureDevOpsProject
|
$AzureDevOpsProject = $buildInfo.azureDevOpsProject
|
||||||
|
|
@ -75,3 +73,5 @@ jobs:
|
||||||
}
|
}
|
||||||
env:
|
env:
|
||||||
MAESTRO_API_TOKEN: $(MaestroApiAccessToken)
|
MAESTRO_API_TOKEN: $(MaestroApiAccessToken)
|
||||||
|
BARBuildId: ${{ parameters.BARBuildId }}
|
||||||
|
PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ param(
|
||||||
|
|
||||||
& $PSScriptRoot\Download.ps1 "https://dot.net/v1/dotnet-install.ps1" $PSScriptRoot\dotnet-install.ps1
|
& $PSScriptRoot\Download.ps1 "https://dot.net/v1/dotnet-install.ps1" $PSScriptRoot\dotnet-install.ps1
|
||||||
Write-Host "Download of dotnet-install.ps1 complete..."
|
Write-Host "Download of dotnet-install.ps1 complete..."
|
||||||
Write-Host "Installing SDK...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir"
|
Write-Host "Installing SDK...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir -NoPath"
|
||||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir"
|
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir -NoPath"
|
||||||
Write-Host "Installing Runtime...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir"
|
Write-Host "Installing Runtime...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir -NoPath"
|
||||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir"
|
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir -NoPath"
|
||||||
Write-Host "InstallDotNet.ps1 complete..."
|
Write-Host "InstallDotNet.ps1 complete..."
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
},
|
},
|
||||||
"msbuild-sdks": {
|
"msbuild-sdks": {
|
||||||
"Yarn.MSBuild": "1.15.2",
|
"Yarn.MSBuild": "1.15.2",
|
||||||
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20411.8",
|
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20419.21",
|
||||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20411.8"
|
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20419.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -57,7 +58,24 @@ namespace Microsoft.AspNetCore.Antiforgery
|
||||||
{
|
{
|
||||||
// Check the content-type before accessing the form collection to make sure
|
// Check the content-type before accessing the form collection to make sure
|
||||||
// we report errors gracefully.
|
// we report errors gracefully.
|
||||||
var form = await httpContext.Request.ReadFormAsync();
|
IFormCollection form;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
form = await httpContext.Request.ReadFormAsync();
|
||||||
|
}
|
||||||
|
catch (InvalidDataException ex)
|
||||||
|
{
|
||||||
|
// ReadFormAsync can throw InvalidDataException if the form content is malformed.
|
||||||
|
// Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.
|
||||||
|
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
// Reading the request body (which happens as part of ReadFromAsync) may throw an exception if a client disconnects.
|
||||||
|
// Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.
|
||||||
|
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);
|
||||||
|
}
|
||||||
|
|
||||||
requestToken = form[_options.FormFieldName];
|
requestToken = form[_options.FormFieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,9 @@
|
||||||
<data name="AntiforgeryToken_TokensSwapped" xml:space="preserve">
|
<data name="AntiforgeryToken_TokensSwapped" xml:space="preserve">
|
||||||
<value>Validation of the provided antiforgery token failed. The cookie token and the request token were swapped.</value>
|
<value>Validation of the provided antiforgery token failed. The cookie token and the request token were swapped.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AntiforgeryToken_UnableToReadRequest" xml:space="preserve">
|
||||||
|
<value>Unable to read the antiforgery request token from the posted form.</value>
|
||||||
|
</data>
|
||||||
<data name="AntiforgeryToken_UsernameMismatch" xml:space="preserve">
|
<data name="AntiforgeryToken_UsernameMismatch" xml:space="preserve">
|
||||||
<value>The provided antiforgery token was meant for user "{0}", but the current user is "{1}".</value>
|
<value>The provided antiforgery token was meant for user "{0}", but the current user is "{1}".</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
@ -235,6 +237,56 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
Assert.Null(tokenSet.RequestToken);
|
Assert.Null(tokenSet.RequestToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetRequestTokens_ReadFormAsyncThrowsIOException_ThrowsAntiforgeryValidationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var ioException = new IOException();
|
||||||
|
var httpContext = new Mock<HttpContext>();
|
||||||
|
|
||||||
|
httpContext.Setup(r => r.Request.Cookies).Returns(Mock.Of<IRequestCookieCollection>());
|
||||||
|
httpContext.SetupGet(r => r.Request.HasFormContentType).Returns(true);
|
||||||
|
httpContext.Setup(r => r.Request.ReadFormAsync(It.IsAny<CancellationToken>())).Throws(ioException);
|
||||||
|
|
||||||
|
var options = new AntiforgeryOptions
|
||||||
|
{
|
||||||
|
Cookie = { Name = "cookie-name" },
|
||||||
|
FormFieldName = "form-field-name",
|
||||||
|
HeaderName = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<AntiforgeryValidationException>(() => tokenStore.GetRequestTokensAsync(httpContext.Object));
|
||||||
|
Assert.Same(ioException, ex.InnerException);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetRequestTokens_ReadFormAsyncThrowsInvalidDataException_ThrowsAntiforgeryValidationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var exception = new InvalidDataException();
|
||||||
|
var httpContext = new Mock<HttpContext>();
|
||||||
|
|
||||||
|
httpContext.Setup(r => r.Request.Cookies).Returns(Mock.Of<IRequestCookieCollection>());
|
||||||
|
httpContext.SetupGet(r => r.Request.HasFormContentType).Returns(true);
|
||||||
|
httpContext.Setup(r => r.Request.ReadFormAsync(It.IsAny<CancellationToken>())).Throws(exception);
|
||||||
|
|
||||||
|
var options = new AntiforgeryOptions
|
||||||
|
{
|
||||||
|
Cookie = { Name = "cookie-name" },
|
||||||
|
FormFieldName = "form-field-name",
|
||||||
|
HeaderName = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<AntiforgeryValidationException>(() => tokenStore.GetRequestTokensAsync(httpContext.Object));
|
||||||
|
Assert.Same(exception, ex.InnerException);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(false, CookieSecurePolicy.SameAsRequest, null)]
|
[InlineData(false, CookieSecurePolicy.SameAsRequest, null)]
|
||||||
[InlineData(true, CookieSecurePolicy.SameAsRequest, true)]
|
[InlineData(true, CookieSecurePolicy.SameAsRequest, true)]
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Components
|
||||||
(
|
(
|
||||||
propertyName: property.Name,
|
propertyName: property.Name,
|
||||||
propertyType: property.PropertyType,
|
propertyType: property.PropertyType,
|
||||||
setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false)
|
setter: new PropertySetter(type, property)
|
||||||
)).ToArray();
|
)).ToArray();
|
||||||
|
|
||||||
return Initialize;
|
return Initialize;
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetProperty(object target, IPropertySetter writer, string parameterName, object value)
|
static void SetProperty(object target, PropertySetter writer, string parameterName, object value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -246,13 +246,13 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
private class WritersForType
|
private class WritersForType
|
||||||
{
|
{
|
||||||
private const int MaxCachedWriterLookups = 100;
|
private const int MaxCachedWriterLookups = 100;
|
||||||
private readonly Dictionary<string, IPropertySetter> _underlyingWriters;
|
private readonly Dictionary<string, PropertySetter> _underlyingWriters;
|
||||||
private readonly ConcurrentDictionary<string, IPropertySetter?> _referenceEqualityWritersCache;
|
private readonly ConcurrentDictionary<string, PropertySetter?> _referenceEqualityWritersCache;
|
||||||
|
|
||||||
public WritersForType(Type targetType)
|
public WritersForType(Type targetType)
|
||||||
{
|
{
|
||||||
_underlyingWriters = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
|
_underlyingWriters = new Dictionary<string, PropertySetter>(StringComparer.OrdinalIgnoreCase);
|
||||||
_referenceEqualityWritersCache = new ConcurrentDictionary<string, IPropertySetter?>(ReferenceEqualityComparer.Instance);
|
_referenceEqualityWritersCache = new ConcurrentDictionary<string, PropertySetter?>(ReferenceEqualityComparer.Instance);
|
||||||
|
|
||||||
foreach (var propertyInfo in GetCandidateBindableProperties(targetType))
|
foreach (var propertyInfo in GetCandidateBindableProperties(targetType))
|
||||||
{
|
{
|
||||||
|
|
@ -271,7 +271,10 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
$"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public.");
|
$"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null);
|
var propertySetter = new PropertySetter(targetType, propertyInfo)
|
||||||
|
{
|
||||||
|
Cascading = cascadingParameterAttribute != null,
|
||||||
|
};
|
||||||
|
|
||||||
if (_underlyingWriters.ContainsKey(propertyName))
|
if (_underlyingWriters.ContainsKey(propertyName))
|
||||||
{
|
{
|
||||||
|
|
@ -298,17 +301,17 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo);
|
ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: false);
|
CaptureUnmatchedValuesWriter = new PropertySetter(targetType, propertyInfo);
|
||||||
CaptureUnmatchedValuesPropertyName = propertyInfo.Name;
|
CaptureUnmatchedValuesPropertyName = propertyInfo.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPropertySetter? CaptureUnmatchedValuesWriter { get; }
|
public PropertySetter? CaptureUnmatchedValuesWriter { get; }
|
||||||
|
|
||||||
public string? CaptureUnmatchedValuesPropertyName { get; }
|
public string? CaptureUnmatchedValuesPropertyName { get; }
|
||||||
|
|
||||||
public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out IPropertySetter writer)
|
public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out PropertySetter writer)
|
||||||
{
|
{
|
||||||
// In intensive parameter-passing scenarios, one of the most expensive things we do is the
|
// In intensive parameter-passing scenarios, one of the most expensive things we do is the
|
||||||
// lookup from parameterName to writer. Pre-5.0 that was because of the string hashing.
|
// lookup from parameterName to writer. Pre-5.0 that was because of the string hashing.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,55 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.Reflection
|
namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
{
|
{
|
||||||
internal interface IPropertySetter
|
internal sealed class PropertySetter
|
||||||
{
|
{
|
||||||
bool Cascading { get; }
|
private static readonly MethodInfo CallPropertySetterOpenGenericMethod =
|
||||||
|
typeof(PropertySetter).GetMethod(nameof(CallPropertySetter), BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
void SetValue(object target, object value);
|
private readonly Action<object, object> _setterDelegate;
|
||||||
|
|
||||||
|
public PropertySetter(Type targetType, PropertyInfo property)
|
||||||
|
{
|
||||||
|
if (property.SetMethod == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Cannot provide a value for property " +
|
||||||
|
$"'{property.Name}' on type '{targetType.FullName}' because the property " +
|
||||||
|
$"has no setter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var setMethod = property.SetMethod;
|
||||||
|
|
||||||
|
var propertySetterAsAction =
|
||||||
|
setMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(targetType, property.PropertyType));
|
||||||
|
var callPropertySetterClosedGenericMethod =
|
||||||
|
CallPropertySetterOpenGenericMethod.MakeGenericMethod(targetType, property.PropertyType);
|
||||||
|
_setterDelegate = (Action<object, object>)
|
||||||
|
callPropertySetterClosedGenericMethod.CreateDelegate(typeof(Action<object, object>), propertySetterAsAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Cascading { get; init; }
|
||||||
|
|
||||||
|
public void SetValue(object target, object value) => _setterDelegate(target, value);
|
||||||
|
|
||||||
|
private static void CallPropertySetter<TTarget, TValue>(
|
||||||
|
Action<TTarget, TValue> setter,
|
||||||
|
object target,
|
||||||
|
object value)
|
||||||
|
where TTarget : notnull
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
setter((TTarget)target, default!);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setter((TTarget)target, (TValue)value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,46 +44,5 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
||||||
|
|
||||||
return dictionary.Values.SelectMany(p => p);
|
return dictionary.Values.SelectMany(p => p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property, bool cascading)
|
|
||||||
{
|
|
||||||
if (property.SetMethod == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Cannot provide a value for property " +
|
|
||||||
$"'{property.Name}' on type '{targetType.FullName}' because the property " +
|
|
||||||
$"has no setter.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (IPropertySetter)Activator.CreateInstance(
|
|
||||||
typeof(PropertySetter<,>).MakeGenericType(targetType, property.PropertyType),
|
|
||||||
property.SetMethod,
|
|
||||||
cascading)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertySetter<TTarget, TValue> : IPropertySetter where TTarget : notnull
|
|
||||||
{
|
|
||||||
private readonly Action<TTarget, TValue> _setterDelegate;
|
|
||||||
|
|
||||||
public PropertySetter(MethodInfo setMethod, bool cascading)
|
|
||||||
{
|
|
||||||
_setterDelegate = (Action<TTarget, TValue>)Delegate.CreateDelegate(
|
|
||||||
typeof(Action<TTarget, TValue>), setMethod);
|
|
||||||
Cascading = cascading;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Cascading { get; }
|
|
||||||
|
|
||||||
public void SetValue(object target, object value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
_setterDelegate((TTarget)target, default!);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_setterDelegate((TTarget)target, (TValue)value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a handler that should be called before navigating to a new page.
|
/// Gets or sets a handler that should be called before navigating to a new page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public Func<NavigationContext, Task>? OnNavigateAsync { get; set; }
|
[Parameter] public EventCallback<NavigationContext> OnNavigateAsync { get; set; }
|
||||||
|
|
||||||
private RouteTable Routes { get; set; }
|
private RouteTable Routes { get; set; }
|
||||||
|
|
||||||
|
|
@ -115,8 +115,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
||||||
if (!_onNavigateCalled)
|
if (!_onNavigateCalled)
|
||||||
{
|
{
|
||||||
_onNavigateCalled = true;
|
_onNavigateCalled = true;
|
||||||
await RunOnNavigateWithRefreshAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);
|
await RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Refresh(isNavigationIntercepted: false);
|
Refresh(isNavigationIntercepted: false);
|
||||||
|
|
@ -206,9 +205,8 @@ namespace Microsoft.AspNetCore.Components.Routing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ValueTask<bool> RunOnNavigateAsync(string path, Task previousOnNavigate)
|
internal async ValueTask RunOnNavigateAsync(string path, bool isNavigationIntercepted)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Cancel the CTS instead of disposing it, since disposing does not
|
// Cancel the CTS instead of disposing it, since disposing does not
|
||||||
// actually cancel and can cause unintended Object Disposed Exceptions.
|
// actually cancel and can cause unintended Object Disposed Exceptions.
|
||||||
// This effectivelly cancels the previously running task and completes it.
|
// This effectivelly cancels the previously running task and completes it.
|
||||||
|
|
@ -217,59 +215,35 @@ namespace Microsoft.AspNetCore.Components.Routing
|
||||||
// before starting the next one. This avoid race conditions where the cancellation
|
// before starting the next one. This avoid race conditions where the cancellation
|
||||||
// for the previous task was set but not fully completed by the time we get to this
|
// for the previous task was set but not fully completed by the time we get to this
|
||||||
// invocation.
|
// invocation.
|
||||||
await previousOnNavigate;
|
await _previousOnNavigateTask;
|
||||||
|
|
||||||
if (OnNavigateAsync == null)
|
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
_previousOnNavigateTask = tcs.Task;
|
||||||
|
|
||||||
|
if (!OnNavigateAsync.HasDelegate)
|
||||||
{
|
{
|
||||||
return true;
|
Refresh(isNavigationIntercepted);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onNavigateCts = new CancellationTokenSource();
|
_onNavigateCts = new CancellationTokenSource();
|
||||||
var navigateContext = new NavigationContext(path, _onNavigateCts.Token);
|
var navigateContext = new NavigationContext(path, _onNavigateCts.Token);
|
||||||
|
|
||||||
|
var cancellationTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
navigateContext.CancellationToken.Register(state =>
|
||||||
|
((TaskCompletionSource)state).SetResult(), cancellationTcs);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Navigating != null)
|
// Task.WhenAny returns a Task<Task> so we need to await twice to unwrap the exception
|
||||||
{
|
var task = await Task.WhenAny(OnNavigateAsync.InvokeAsync(navigateContext), cancellationTcs.Task);
|
||||||
_renderHandle.Render(Navigating);
|
await task;
|
||||||
}
|
tcs.SetResult();
|
||||||
await OnNavigateAsync(navigateContext);
|
Refresh(isNavigationIntercepted);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException e)
|
|
||||||
{
|
|
||||||
if (e.CancellationToken != navigateContext.CancellationToken)
|
|
||||||
{
|
|
||||||
var rethrownException = new InvalidOperationException("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", e);
|
|
||||||
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(rethrownException));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(e));
|
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task RunOnNavigateWithRefreshAsync(string path, bool isNavigationIntercepted)
|
|
||||||
{
|
|
||||||
// We cache the Task representing the previously invoked RunOnNavigateWithRefreshAsync
|
|
||||||
// that is stored. Then we create a new one that represents our current invocation and store it
|
|
||||||
// globally for the next invocation. This allows us to check inside `RunOnNavigateAsync` if the
|
|
||||||
// previous OnNavigateAsync task has fully completed before starting the next one.
|
|
||||||
var previousTask = _previousOnNavigateTask;
|
|
||||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
||||||
_previousOnNavigateTask = tcs.Task;
|
|
||||||
|
|
||||||
// And pass an indicator for the previous task to the currently running one.
|
|
||||||
var shouldRefresh = await RunOnNavigateAsync(path, previousTask);
|
|
||||||
tcs.SetResult();
|
|
||||||
if (shouldRefresh)
|
|
||||||
{
|
|
||||||
Refresh(isNavigationIntercepted);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLocationChanged(object sender, LocationChangedEventArgs args)
|
private void OnLocationChanged(object sender, LocationChangedEventArgs args)
|
||||||
|
|
@ -277,7 +251,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
||||||
_locationAbsolute = args.Location;
|
_locationAbsolute = args.Location;
|
||||||
if (_renderHandle.IsInitialized && Routes != null)
|
if (_renderHandle.IsInitialized && Routes != null)
|
||||||
{
|
{
|
||||||
_ = RunOnNavigateWithRefreshAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted);
|
_ = RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@ using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Moq;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.Test.Routing
|
namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
{
|
{
|
||||||
|
|
@ -42,49 +40,26 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var called = false;
|
var called = false;
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||||
{
|
{
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
called = true;
|
called = true;
|
||||||
}
|
};
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(called);
|
Assert.True(called);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task CanHandleSingleFailedOnNavigateAsync()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var called = false;
|
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
|
||||||
{
|
|
||||||
called = true;
|
|
||||||
await Task.CompletedTask;
|
|
||||||
throw new Exception("This is an uncaught exception.");
|
|
||||||
}
|
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.True(called);
|
|
||||||
Assert.Single(_renderer.HandledExceptions);
|
|
||||||
var unhandledException = _renderer.HandledExceptions[0];
|
|
||||||
Assert.Equal("This is an uncaught exception.", unhandledException.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CanceledFailedOnNavigateAsyncDoesNothing()
|
public async Task CanceledFailedOnNavigateAsyncDoesNothing()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var onNavigateInvoked = 0;
|
var onNavigateInvoked = 0;
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||||
{
|
{
|
||||||
onNavigateInvoked += 1;
|
onNavigateInvoked += 1;
|
||||||
if (args.Path.EndsWith("jan"))
|
if (args.Path.EndsWith("jan"))
|
||||||
|
|
@ -92,22 +67,18 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
await Task.Delay(Timeout.Infinite, args.CancellationToken);
|
await Task.Delay(Timeout.Infinite, args.CancellationToken);
|
||||||
throw new Exception("This is an uncaught exception.");
|
throw new Exception("This is an uncaught exception.");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
var refreshCalled = false;
|
var refreshCalled = 0;
|
||||||
_renderer.OnUpdateDisplay = (renderBatch) =>
|
_renderer.OnUpdateDisplay = (renderBatch) =>
|
||||||
{
|
{
|
||||||
if (!refreshCalled)
|
refreshCalled += 1;
|
||||||
{
|
return;
|
||||||
refreshCalled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
|
||||||
};
|
};
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var janTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
var janTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||||
var febTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
var febTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||||
|
|
||||||
await janTask;
|
await janTask;
|
||||||
await febTask;
|
await febTask;
|
||||||
|
|
@ -115,28 +86,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
// Assert that we render the second route component and don't throw an exception
|
// Assert that we render the second route component and don't throw an exception
|
||||||
Assert.Empty(_renderer.HandledExceptions);
|
Assert.Empty(_renderer.HandledExceptions);
|
||||||
Assert.Equal(2, onNavigateInvoked);
|
Assert.Equal(2, onNavigateInvoked);
|
||||||
}
|
Assert.Equal(2, refreshCalled);
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task CanHandleSingleCancelledOnNavigateAsync()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
|
||||||
{
|
|
||||||
var tcs = new TaskCompletionSource<int>();
|
|
||||||
tcs.TrySetCanceled();
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
_renderer.OnUpdateDisplay = (renderBatch) => Assert.True(false, "OnUpdateDisplay called more than once.");
|
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Single(_renderer.HandledExceptions);
|
|
||||||
var unhandledException = _renderer.HandledExceptions[0];
|
|
||||||
Assert.Equal("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", unhandledException.Message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -144,7 +94,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var triggerCancel = new TaskCompletionSource();
|
var triggerCancel = new TaskCompletionSource();
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||||
{
|
{
|
||||||
if (args.Path.EndsWith("jan"))
|
if (args.Path.EndsWith("jan"))
|
||||||
{
|
{
|
||||||
|
|
@ -153,7 +103,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
tcs.TrySetCanceled();
|
tcs.TrySetCanceled();
|
||||||
await tcs.Task;
|
await tcs.Task;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
var refreshCalled = false;
|
var refreshCalled = false;
|
||||||
_renderer.OnUpdateDisplay = (renderBatch) =>
|
_renderer.OnUpdateDisplay = (renderBatch) =>
|
||||||
{
|
{
|
||||||
|
|
@ -164,11 +114,11 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
}
|
}
|
||||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||||
};
|
};
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||||
|
|
||||||
// Act (start the operations then await them)
|
// Act (start the operations then await them)
|
||||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||||
triggerCancel.TrySetResult();
|
triggerCancel.TrySetResult();
|
||||||
|
|
||||||
await jan;
|
await jan;
|
||||||
|
|
@ -180,16 +130,16 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var cancelled = "";
|
var cancelled = "";
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||||
{
|
{
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
args.CancellationToken.Register(() => cancelled = args.Path);
|
args.CancellationToken.Register(() => cancelled = args.Path);
|
||||||
};
|
};
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
_ = _router.RunOnNavigateWithRefreshAsync("jan", false);
|
_ = _router.RunOnNavigateAsync("jan", false);
|
||||||
_ = _router.RunOnNavigateWithRefreshAsync("feb", false);
|
_ = _router.RunOnNavigateAsync("feb", false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var expected = "jan";
|
var expected = "jan";
|
||||||
|
|
@ -200,7 +150,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
public async Task RefreshesOnceOnCancelledOnNavigateAsync()
|
public async Task RefreshesOnceOnCancelledOnNavigateAsync()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
async Task OnNavigateAsync(NavigationContext args)
|
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||||
{
|
{
|
||||||
if (args.Path.EndsWith("jan"))
|
if (args.Path.EndsWith("jan"))
|
||||||
{
|
{
|
||||||
|
|
@ -217,11 +167,11 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||||
}
|
}
|
||||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||||
};
|
};
|
||||||
_router.OnNavigateAsync = OnNavigateAsync;
|
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||||
|
|
||||||
await jan;
|
await jan;
|
||||||
await feb;
|
await feb;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@
|
||||||
"src\\Components\\WebAssembly\\DebugProxy\\src\\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj",
|
"src\\Components\\WebAssembly\\DebugProxy\\src\\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj",
|
||||||
"src\\Components\\WebAssembly\\DevServer\\src\\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj",
|
"src\\Components\\WebAssembly\\DevServer\\src\\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj",
|
||||||
"src\\Components\\WebAssembly\\JSInterop\\src\\Microsoft.JSInterop.WebAssembly.csproj",
|
"src\\Components\\WebAssembly\\JSInterop\\src\\Microsoft.JSInterop.WebAssembly.csproj",
|
||||||
|
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||||
|
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
||||||
|
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
||||||
|
"src\\Components\\WebAssembly\\Sdk\\tools\\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj",
|
||||||
"src\\Components\\WebAssembly\\Server\\src\\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj",
|
"src\\Components\\WebAssembly\\Server\\src\\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj",
|
||||||
"src\\Components\\WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj",
|
"src\\Components\\WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj",
|
||||||
"src\\Components\\WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj",
|
"src\\Components\\WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj",
|
||||||
|
|
@ -31,10 +35,9 @@
|
||||||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
|
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
|
||||||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
|
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
|
||||||
"src\\Components\\WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
|
"src\\Components\\WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
|
||||||
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Client\\Wasm.Authentication.Client.csproj",
|
||||||
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Server\\Wasm.Authentication.Server.csproj",
|
||||||
"src\\Components\\WebAssembly\\Sdk\\tools\\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj",
|
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Shared\\Wasm.Authentication.Shared.csproj",
|
||||||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
|
||||||
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
||||||
"src\\Components\\Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
"src\\Components\\Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
||||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\ConsoleHost\\Wasm.Performance.ConsoleHost.csproj",
|
"src\\Components\\benchmarkapps\\Wasm.Performance\\ConsoleHost\\Wasm.Performance.ConsoleHost.csproj",
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
||||||
// really don't, you can pass an empty object then ignore it. Ensuring it's nonnull
|
// really don't, you can pass an empty object then ignore it. Ensuring it's nonnull
|
||||||
// simplifies things for all consumers of EditContext.
|
// simplifies things for all consumers of EditContext.
|
||||||
Model = model ?? throw new ArgumentNullException(nameof(model));
|
Model = model ?? throw new ArgumentNullException(nameof(model));
|
||||||
|
Properties = new EditContextProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -62,6 +63,11 @@ namespace Microsoft.AspNetCore.Components.Forms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object Model { get; }
|
public object Model { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of arbitrary properties associated with this instance.
|
||||||
|
/// </summary>
|
||||||
|
public EditContextProperties Properties { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signals that the value for the specified field has changed.
|
/// Signals that the value for the specified field has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (c) .NET 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.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Forms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds arbitrary key/value pairs associated with an <see cref="EditContext"/>.
|
||||||
|
/// This can be used to track additional metadata for application-specific purposes.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EditContextProperties
|
||||||
|
{
|
||||||
|
// We don't want to expose any way of enumerating the underlying dictionary, because that would
|
||||||
|
// prevent its usage to store private information. So we only expose an indexer and TryGetValue.
|
||||||
|
private Dictionary<object, object>? _contents;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key under which the value is stored.</param>
|
||||||
|
/// <returns>The stored value.</returns>
|
||||||
|
public object this[object key]
|
||||||
|
{
|
||||||
|
get => _contents is null ? throw new KeyNotFoundException() : _contents[key];
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_contents ??= new Dictionary<object, object>();
|
||||||
|
_contents[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value associated with the specified key, if any.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key under which the value is stored.</param>
|
||||||
|
/// <param name="value">The value, if present.</param>
|
||||||
|
/// <returns>True if the value was present, otherwise false.</returns>
|
||||||
|
public bool TryGetValue(object key, [NotNullWhen(true)] out object? value)
|
||||||
|
{
|
||||||
|
if (_contents is null)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _contents.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the specified entry from the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key of the entry to be removed.</param>
|
||||||
|
/// <returns>True if the value was present, otherwise false.</returns>
|
||||||
|
public bool Remove(object key)
|
||||||
|
{
|
||||||
|
return _contents?.Remove(key) ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -252,6 +253,76 @@ namespace Microsoft.AspNetCore.Components.Forms
|
||||||
Assert.True(editContext.IsModified(editContext.Field(nameof(EquatableModel.Property))));
|
Assert.True(editContext.IsModified(editContext.Field(nameof(EquatableModel.Property))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Properties_CanRetrieveViaIndexer()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var editContext = new EditContext(new object());
|
||||||
|
var key1 = new object();
|
||||||
|
var key2 = new object();
|
||||||
|
var key3 = new object();
|
||||||
|
var value1 = new object();
|
||||||
|
var value2 = new object();
|
||||||
|
|
||||||
|
// Initially, the values are not present
|
||||||
|
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key1]);
|
||||||
|
|
||||||
|
// Can store and retrieve values
|
||||||
|
editContext.Properties[key1] = value1;
|
||||||
|
editContext.Properties[key2] = value2;
|
||||||
|
Assert.Same(value1, editContext.Properties[key1]);
|
||||||
|
Assert.Same(value2, editContext.Properties[key2]);
|
||||||
|
|
||||||
|
// Unrelated keys are still not found
|
||||||
|
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Properties_CanRetrieveViaTryGetValue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var editContext = new EditContext(new object());
|
||||||
|
var key1 = new object();
|
||||||
|
var key2 = new object();
|
||||||
|
var key3 = new object();
|
||||||
|
var value1 = new object();
|
||||||
|
var value2 = new object();
|
||||||
|
|
||||||
|
// Initially, the values are not present
|
||||||
|
Assert.False(editContext.Properties.TryGetValue(key1, out _));
|
||||||
|
|
||||||
|
// Can store and retrieve values
|
||||||
|
editContext.Properties[key1] = value1;
|
||||||
|
editContext.Properties[key2] = value2;
|
||||||
|
Assert.True(editContext.Properties.TryGetValue(key1, out var retrievedValue1));
|
||||||
|
Assert.True(editContext.Properties.TryGetValue(key2, out var retrievedValue2));
|
||||||
|
Assert.Same(value1, retrievedValue1);
|
||||||
|
Assert.Same(value2, retrievedValue2);
|
||||||
|
|
||||||
|
// Unrelated keys are still not found
|
||||||
|
Assert.False(editContext.Properties.TryGetValue(key3, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Properties_CanRemove()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var editContext = new EditContext(new object());
|
||||||
|
var key = new object();
|
||||||
|
var value = new object();
|
||||||
|
editContext.Properties[key] = value;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var resultForExistingKey = editContext.Properties.Remove(key);
|
||||||
|
var resultForNonExistingKey = editContext.Properties.Remove(new object());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(resultForExistingKey);
|
||||||
|
Assert.False(resultForNonExistingKey);
|
||||||
|
Assert.False(editContext.Properties.TryGetValue(key, out _));
|
||||||
|
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key]);
|
||||||
|
}
|
||||||
|
|
||||||
class EquatableModel : IEquatable<EquatableModel>
|
class EquatableModel : IEquatable<EquatableModel>
|
||||||
{
|
{
|
||||||
public string Property { get; set; } = "";
|
public string Property { get; set; } = "";
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,7 @@ namespace Ignitor
|
||||||
_hubConnection = builder.Build();
|
_hubConnection = builder.Build();
|
||||||
|
|
||||||
HubConnection.On<int, string>("JS.AttachComponent", OnAttachComponent);
|
HubConnection.On<int, string>("JS.AttachComponent", OnAttachComponent);
|
||||||
HubConnection.On<int, string, string>("JS.BeginInvokeJS", OnBeginInvokeJS);
|
HubConnection.On<int, string, string, int, long>("JS.BeginInvokeJS", OnBeginInvokeJS);
|
||||||
HubConnection.On<string>("JS.EndInvokeDotNet", OnEndInvokeDotNet);
|
HubConnection.On<string>("JS.EndInvokeDotNet", OnEndInvokeDotNet);
|
||||||
HubConnection.On<int, byte[]>("JS.RenderBatch", OnRenderBatch);
|
HubConnection.On<int, byte[]>("JS.RenderBatch", OnRenderBatch);
|
||||||
HubConnection.On<string>("JS.Error", OnError);
|
HubConnection.On<string>("JS.Error", OnError);
|
||||||
|
|
@ -401,9 +401,9 @@ namespace Ignitor
|
||||||
NextAttachComponentReceived?.Completion?.TrySetResult(call);
|
NextAttachComponentReceived?.Completion?.TrySetResult(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson)
|
private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId)
|
||||||
{
|
{
|
||||||
var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson);
|
var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson, resultType, targetInstanceId);
|
||||||
Operations?.JSInteropCalls.Enqueue(call);
|
Operations?.JSInteropCalls.Enqueue(call);
|
||||||
JSInterop?.Invoke(call);
|
JSInterop?.Invoke(call);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,19 @@ namespace Ignitor
|
||||||
{
|
{
|
||||||
public class CapturedJSInteropCall
|
public class CapturedJSInteropCall
|
||||||
{
|
{
|
||||||
public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson)
|
public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId)
|
||||||
{
|
{
|
||||||
AsyncHandle = asyncHandle;
|
AsyncHandle = asyncHandle;
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
ArgsJson = argsJson;
|
ArgsJson = argsJson;
|
||||||
|
ResultType = resultType;
|
||||||
|
TargetInstanceId = targetInstanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int AsyncHandle { get; }
|
public int AsyncHandle { get; }
|
||||||
public string Identifier { get; }
|
public string Identifier { get; }
|
||||||
public string ArgsJson { get; }
|
public string ArgsJson { get; }
|
||||||
|
public int ResultType { get; }
|
||||||
|
public long TargetInstanceId { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||||
JsonSerializer.Serialize(new[] { callId, success, resultOrError }, JsonSerializerOptions));
|
JsonSerializer.Serialize(new[] { callId, success, resultOrError }, JsonSerializerOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
|
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||||
{
|
{
|
||||||
if (_clientProxy is null)
|
if (_clientProxy is null)
|
||||||
{
|
{
|
||||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||||
|
|
||||||
Log.BeginInvokeJS(_logger, asyncHandle, identifier);
|
Log.BeginInvokeJS(_logger, asyncHandle, identifier);
|
||||||
|
|
||||||
_clientProxy.SendAsync("JS.BeginInvokeJS", asyncHandle, identifier, argsJson);
|
_clientProxy.SendAsync("JS.BeginInvokeJS", asyncHandle, identifier, argsJson, (int)resultType, targetInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Log
|
public static class Log
|
||||||
|
|
|
||||||
|
|
@ -59,13 +59,13 @@ namespace Microsoft.AspNetCore.Components.Server
|
||||||
{
|
{
|
||||||
private readonly IDataProtector _dataProtector;
|
private readonly IDataProtector _dataProtector;
|
||||||
private readonly ILogger<ServerComponentDeserializer> _logger;
|
private readonly ILogger<ServerComponentDeserializer> _logger;
|
||||||
private readonly ServerComponentTypeCache _rootComponentTypeCache;
|
private readonly RootComponentTypeCache _rootComponentTypeCache;
|
||||||
private readonly ComponentParameterDeserializer _parametersDeserializer;
|
private readonly ComponentParameterDeserializer _parametersDeserializer;
|
||||||
|
|
||||||
public ServerComponentDeserializer(
|
public ServerComponentDeserializer(
|
||||||
IDataProtectionProvider dataProtectionProvider,
|
IDataProtectionProvider dataProtectionProvider,
|
||||||
ILogger<ServerComponentDeserializer> logger,
|
ILogger<ServerComponentDeserializer> logger,
|
||||||
ServerComponentTypeCache rootComponentTypeCache,
|
RootComponentTypeCache rootComponentTypeCache,
|
||||||
ComponentParameterDeserializer parametersDeserializer)
|
ComponentParameterDeserializer parametersDeserializer)
|
||||||
{
|
{
|
||||||
// When we protect the data we use a time-limited data protector with the
|
// When we protect the data we use a time-limited data protector with the
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<StaticFileOptions>, ConfigureStaticFilesOptions>());
|
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<StaticFileOptions>, ConfigureStaticFilesOptions>());
|
||||||
services.TryAddSingleton<CircuitFactory>();
|
services.TryAddSingleton<CircuitFactory>();
|
||||||
services.TryAddSingleton<ServerComponentDeserializer>();
|
services.TryAddSingleton<ServerComponentDeserializer>();
|
||||||
services.TryAddSingleton<ServerComponentTypeCache>();
|
services.TryAddSingleton<RootComponentTypeCache>();
|
||||||
services.TryAddSingleton<ComponentParameterDeserializer>();
|
services.TryAddSingleton<ComponentParameterDeserializer>();
|
||||||
services.TryAddSingleton<ComponentParametersTypeCache>();
|
services.TryAddSingleton<ComponentParametersTypeCache>();
|
||||||
services.TryAddSingleton<CircuitIdFactory>();
|
services.TryAddSingleton<CircuitIdFactory>();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||||
<Description>Runtime server features for ASP.NET Core Components.</Description>
|
<Description>Runtime server features for ASP.NET Core Components.</Description>
|
||||||
|
|
@ -54,6 +54,8 @@
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="Circuits" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="Circuits" />
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
||||||
|
<Compile Include="$(ComponentsSharedSourceRoot)src\ComponentParametersTypeCache.cs" />
|
||||||
|
<Compile Include="$(ComponentsSharedSourceRoot)src\RootComponentTypeCache.cs" />
|
||||||
|
|
||||||
<Compile Include="..\..\Shared\src\BrowserNavigationManagerInterop.cs" />
|
<Compile Include="..\..\Shared\src\BrowserNavigationManagerInterop.cs" />
|
||||||
<Compile Include="..\..\Shared\src\JsonSerializerOptionsProvider.cs" />
|
<Compile Include="..\..\Shared\src\JsonSerializerOptionsProvider.cs" />
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||||
return new ServerComponentDeserializer(
|
return new ServerComponentDeserializer(
|
||||||
_ephemeralDataProtectionProvider,
|
_ephemeralDataProtectionProvider,
|
||||||
NullLogger<ServerComponentDeserializer>.Instance,
|
NullLogger<ServerComponentDeserializer>.Instance,
|
||||||
new ServerComponentTypeCache(),
|
new RootComponentTypeCache(),
|
||||||
new ComponentParameterDeserializer(NullLogger<ComponentParameterDeserializer>.Instance, new ComponentParametersTypeCache()));
|
new ComponentParameterDeserializer(NullLogger<ComponentParameterDeserializer>.Instance, new ComponentParametersTypeCache()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using System.Reflection;
|
||||||
namespace Microsoft.AspNetCore.Components
|
namespace Microsoft.AspNetCore.Components
|
||||||
{
|
{
|
||||||
// A cache for root component types
|
// A cache for root component types
|
||||||
internal class ServerComponentTypeCache
|
internal class RootComponentTypeCache
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<Key, Type> _typeToKeyLookUp = new ConcurrentDictionary<Key, Type>();
|
private readonly ConcurrentDictionary<Key, Type> _typeToKeyLookUp = new ConcurrentDictionary<Key, Type>();
|
||||||
|
|
||||||
|
|
@ -39,14 +39,14 @@ namespace Microsoft.AspNetCore.Components
|
||||||
return assembly.GetType(key.Type, throwOnError: false, ignoreCase: false);
|
return assembly.GetType(key.Type, throwOnError: false, ignoreCase: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Key : IEquatable<Key>
|
private readonly struct Key : IEquatable<Key>
|
||||||
{
|
{
|
||||||
public Key(string assembly, string type) =>
|
public Key(string assembly, string type) =>
|
||||||
(Assembly, Type) = (assembly, type);
|
(Assembly, Type) = (assembly, type);
|
||||||
|
|
||||||
public string Assembly { get; set; }
|
public string Assembly { get; }
|
||||||
|
|
||||||
public string Type { get; set; }
|
public string Type { get; }
|
||||||
|
|
||||||
public override bool Equals(object obj) => Equals((Key)obj);
|
public override bool Equals(object obj) => Equals((Key)obj);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal class BrowserFile : IBrowserFile
|
||||||
|
{
|
||||||
|
internal InputFile Owner { get; set; } = default!;
|
||||||
|
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public DateTime LastModified { get; set; }
|
||||||
|
|
||||||
|
public long Size { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string? RelativePath { get; set; }
|
||||||
|
|
||||||
|
public Stream OpenReadStream(CancellationToken cancellationToken = default)
|
||||||
|
=> Owner.OpenReadStream(this, cancellationToken);
|
||||||
|
|
||||||
|
public Task<IBrowserFile> ToImageFileAsync(string format, int maxWidth, int maxHeight)
|
||||||
|
=> Owner.ConvertToImageFileAsync(this, format, maxWidth, maxHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal abstract class BrowserFileStream : Stream
|
||||||
|
{
|
||||||
|
private long _position;
|
||||||
|
|
||||||
|
protected BrowserFile File { get; }
|
||||||
|
|
||||||
|
protected BrowserFileStream(BrowserFile file)
|
||||||
|
{
|
||||||
|
File = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public override long Length => File.Size;
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => _position;
|
||||||
|
set => throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
=> throw new NotSupportedException("Synchronous reads are not supported.");
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
=> ReadAsync(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
|
||||||
|
|
||||||
|
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
int maxBytesToRead = (int)(Length - Position);
|
||||||
|
|
||||||
|
if (maxBytesToRead > buffer.Length)
|
||||||
|
{
|
||||||
|
maxBytesToRead = buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxBytesToRead <= 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesRead = await CopyFileDataIntoBuffer(_position, buffer.Slice(0, maxBytesToRead), cancellationToken);
|
||||||
|
|
||||||
|
_position += bytesRead;
|
||||||
|
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the data of a file selected from an <see cref="InputFile"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public interface IBrowserFile
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the file.
|
||||||
|
/// </summary>
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the last modified date.
|
||||||
|
/// </summary>
|
||||||
|
DateTime LastModified { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the size of the file in bytes.
|
||||||
|
/// </summary>
|
||||||
|
long Size { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the MIME type of the file.
|
||||||
|
/// </summary>
|
||||||
|
string Type { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the stream for reading the uploaded file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">A cancellation token to signal the cancellation of streaming file data.</param>
|
||||||
|
Stream OpenReadStream(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the current image file to a new one of the specified file type and maximum file dimensions.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The image will be scaled to fit the specified dimensions while preserving the original aspect ratio.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="format">The new image format.</param>
|
||||||
|
/// <param name="maxWith">The maximum image width.</param>
|
||||||
|
/// <param name="maxHeight">The maximum image height</param>
|
||||||
|
/// <returns>A <see cref="Task"/> representing the completion of the operation.</returns>
|
||||||
|
Task<IBrowserFile> ToImageFileAsync(string format, int maxWith, int maxHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +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.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal interface IInputFileJsCallbacks
|
||||||
|
{
|
||||||
|
Task NotifyChange(BrowserFile[] files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Components.Rendering;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A component that wraps the HTML file input element and exposes a <see cref="Stream"/> for each file's contents.
|
||||||
|
/// </summary>
|
||||||
|
public class InputFile : ComponentBase, IInputFileJsCallbacks, IDisposable
|
||||||
|
{
|
||||||
|
private ElementReference _inputFileElement;
|
||||||
|
|
||||||
|
private IJSUnmarshalledRuntime? _jsUnmarshalledRuntime;
|
||||||
|
|
||||||
|
private InputFileJsCallbacksRelay? _jsCallbacksRelay;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private IJSRuntime JSRuntime { get; set; } = default!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private IOptions<RemoteBrowserFileStreamOptions> Options { get; set; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the event callback that will be invoked when the collection of selected files changes.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<InputFileChangeEventArgs> OnChange { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection of additional attributes that will be applied to the input element.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter(CaptureUnmatchedValues = true)]
|
||||||
|
public IDictionary<string, object>? AdditionalAttributes { get; set; }
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_jsUnmarshalledRuntime = JSRuntime as IJSUnmarshalledRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
_jsCallbacksRelay = new InputFileJsCallbacksRelay(this);
|
||||||
|
await JSRuntime.InvokeVoidAsync(InputFileInterop.Init, _jsCallbacksRelay.DotNetReference, _inputFileElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||||
|
{
|
||||||
|
builder.OpenElement(0, "input");
|
||||||
|
builder.AddMultipleAttributes(1, AdditionalAttributes);
|
||||||
|
builder.AddAttribute(2, "type", "file");
|
||||||
|
builder.AddElementReferenceCapture(3, elementReference => _inputFileElement = elementReference);
|
||||||
|
builder.CloseElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Stream OpenReadStream(BrowserFile file, CancellationToken cancellationToken)
|
||||||
|
=> _jsUnmarshalledRuntime != null ?
|
||||||
|
(Stream)new SharedBrowserFileStream(JSRuntime, _jsUnmarshalledRuntime, _inputFileElement, file) :
|
||||||
|
new RemoteBrowserFileStream(JSRuntime, _inputFileElement, file, Options.Value, cancellationToken);
|
||||||
|
|
||||||
|
internal async Task<IBrowserFile> ConvertToImageFileAsync(BrowserFile file, string format, int maxWidth, int maxHeight)
|
||||||
|
{
|
||||||
|
var imageFile = await JSRuntime.InvokeAsync<BrowserFile>(InputFileInterop.ToImageFile, _inputFileElement, file.Id, format, maxWidth, maxHeight);
|
||||||
|
|
||||||
|
imageFile.Owner = this;
|
||||||
|
|
||||||
|
return imageFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task IInputFileJsCallbacks.NotifyChange(BrowserFile[] files)
|
||||||
|
{
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
file.Owner = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OnChange.InvokeAsync(new InputFileChangeEventArgs(files));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
_jsCallbacksRelay?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Supplies information about an <see cref="InputFile.OnChange"/> event being raised.
|
||||||
|
/// </summary>
|
||||||
|
public class InputFileChangeEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The updated file entries list.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<IBrowserFile> Files { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="InputFileChangeEventArgs"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="files">The updated file entries list.</param>
|
||||||
|
public InputFileChangeEventArgs(IReadOnlyList<IBrowserFile> files)
|
||||||
|
{
|
||||||
|
Files = files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal static class InputFileInterop
|
||||||
|
{
|
||||||
|
private const string JsFunctionsPrefix = "_blazorInputFile.";
|
||||||
|
|
||||||
|
public const string Init = JsFunctionsPrefix + "init";
|
||||||
|
|
||||||
|
public const string EnsureArrayBufferReadyForSharedMemoryInterop = JsFunctionsPrefix + "ensureArrayBufferReadyForSharedMemoryInterop";
|
||||||
|
|
||||||
|
public const string ReadFileData = JsFunctionsPrefix + "readFileData";
|
||||||
|
|
||||||
|
public const string ReadFileDataSharedMemory = JsFunctionsPrefix + "readFileDataSharedMemory";
|
||||||
|
|
||||||
|
public const string ToImageFile = JsFunctionsPrefix + "toImageFile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal class InputFileJsCallbacksRelay : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IInputFileJsCallbacks _callbacks;
|
||||||
|
|
||||||
|
public IDisposable DotNetReference { get; }
|
||||||
|
|
||||||
|
public InputFileJsCallbacksRelay(IInputFileJsCallbacks callbacks)
|
||||||
|
{
|
||||||
|
_callbacks = callbacks;
|
||||||
|
|
||||||
|
DotNetReference = DotNetObjectReference.Create(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JSInvokable]
|
||||||
|
public Task NotifyChange(BrowserFile[] files)
|
||||||
|
=> _callbacks.NotifyChange(files);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DotNetReference.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct ReadRequest
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public string InputFileElementReferenceId;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public int FileId;
|
||||||
|
|
||||||
|
[FieldOffset(8)]
|
||||||
|
public long SourceOffset;
|
||||||
|
|
||||||
|
[FieldOffset(16)]
|
||||||
|
public byte[] Destination;
|
||||||
|
|
||||||
|
[FieldOffset(20)]
|
||||||
|
public int DestinationOffset;
|
||||||
|
|
||||||
|
[FieldOffset(24)]
|
||||||
|
public int MaxBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal class RemoteBrowserFileStream : BrowserFileStream
|
||||||
|
{
|
||||||
|
private readonly IJSRuntime _jsRuntime;
|
||||||
|
private readonly ElementReference _inputFileElement;
|
||||||
|
private readonly int _maxSegmentSize;
|
||||||
|
private readonly PipeReader _pipeReader;
|
||||||
|
private readonly CancellationTokenSource _fillBufferCts;
|
||||||
|
private readonly TimeSpan _segmentFetchTimeout;
|
||||||
|
|
||||||
|
private bool _isReadingCompleted;
|
||||||
|
private bool _isDisposed;
|
||||||
|
|
||||||
|
public RemoteBrowserFileStream(
|
||||||
|
IJSRuntime jsRuntime,
|
||||||
|
ElementReference inputFileElement,
|
||||||
|
BrowserFile file,
|
||||||
|
RemoteBrowserFileStreamOptions options,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
: base(file)
|
||||||
|
{
|
||||||
|
_jsRuntime = jsRuntime;
|
||||||
|
_inputFileElement = inputFileElement;
|
||||||
|
_maxSegmentSize = options.SegmentSize;
|
||||||
|
_segmentFetchTimeout = options.SegmentFetchTimeout;
|
||||||
|
|
||||||
|
var pipe = new Pipe(new PipeOptions(pauseWriterThreshold: options.MaxBufferSize, resumeWriterThreshold: options.MaxBufferSize));
|
||||||
|
_pipeReader = pipe.Reader;
|
||||||
|
_fillBufferCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
|
||||||
|
_ = FillBuffer(pipe.Writer, _fillBufferCts.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
long offset = 0;
|
||||||
|
|
||||||
|
while (offset < File.Size)
|
||||||
|
{
|
||||||
|
var pipeBuffer = writer.GetMemory(_maxSegmentSize);
|
||||||
|
var segmentSize = (int)Math.Min(_maxSegmentSize, File.Size - offset);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
readSegmentCts.CancelAfter(_segmentFetchTimeout);
|
||||||
|
|
||||||
|
var bytes = await _jsRuntime.InvokeAsync<byte[]>(
|
||||||
|
InputFileInterop.ReadFileData,
|
||||||
|
readSegmentCts.Token,
|
||||||
|
_inputFileElement,
|
||||||
|
File.Id,
|
||||||
|
offset,
|
||||||
|
segmentSize);
|
||||||
|
|
||||||
|
if (bytes.Length != segmentSize)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"A segment with size {bytes.Length} bytes was received, but {segmentSize} bytes were expected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes.CopyTo(pipeBuffer);
|
||||||
|
writer.Advance(segmentSize);
|
||||||
|
offset += segmentSize;
|
||||||
|
|
||||||
|
var result = await writer.FlushAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsCompleted)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await writer.CompleteAsync(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await writer.CompleteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_isReadingCompleted)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalBytesCopied = 0;
|
||||||
|
|
||||||
|
while (destination.Length > 0)
|
||||||
|
{
|
||||||
|
var result = await _pipeReader.ReadAsync(cancellationToken);
|
||||||
|
var bytesToCopy = (int)Math.Min(result.Buffer.Length, destination.Length);
|
||||||
|
|
||||||
|
if (bytesToCopy == 0)
|
||||||
|
{
|
||||||
|
if (result.IsCompleted)
|
||||||
|
{
|
||||||
|
_isReadingCompleted = true;
|
||||||
|
await _pipeReader.CompleteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var slice = result.Buffer.Slice(0, bytesToCopy);
|
||||||
|
slice.CopyTo(destination.Span);
|
||||||
|
|
||||||
|
_pipeReader.AdvanceTo(slice.End);
|
||||||
|
|
||||||
|
totalBytesCopied += bytesToCopy;
|
||||||
|
destination = destination.Slice(bytesToCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBytesCopied;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fillBufferCts.Cancel();
|
||||||
|
|
||||||
|
_isDisposed = true;
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Repesents configurable options for <see cref="RemoteBrowserFileStream"/>.
|
||||||
|
/// </summary>
|
||||||
|
[UnsupportedOSPlatform("browser")]
|
||||||
|
public class RemoteBrowserFileStreamOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum segment size for file data sent over a SignalR circuit.
|
||||||
|
/// The default value is 20K.
|
||||||
|
/// <para>
|
||||||
|
/// This only has an effect when using Blazor Server.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public int SegmentSize { get; set; } = 20 * 1024; // SignalR limit is 32K.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum internal buffer size for unread data sent over a SignalR circuit.
|
||||||
|
/// <para>
|
||||||
|
/// This only has an effect when using Blazor Server.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public int MaxBufferSize { get; set; } = 1024 * 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the time limit for fetching a segment of file data.
|
||||||
|
/// <para>
|
||||||
|
/// This only has an effect when using Blazor Server.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan SegmentFetchTimeout { get; set; } = TimeSpan.FromSeconds(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||||
|
{
|
||||||
|
internal class SharedBrowserFileStream : BrowserFileStream
|
||||||
|
{
|
||||||
|
private readonly IJSRuntime _jsRuntime;
|
||||||
|
|
||||||
|
private readonly IJSUnmarshalledRuntime _jsUnmarshalledRuntime;
|
||||||
|
|
||||||
|
private readonly ElementReference _inputFileElement;
|
||||||
|
|
||||||
|
public SharedBrowserFileStream(IJSRuntime jsRuntime, IJSUnmarshalledRuntime jsUnmarshalledRuntime, ElementReference inputFileElement, BrowserFile file)
|
||||||
|
: base(file)
|
||||||
|
{
|
||||||
|
_jsRuntime = jsRuntime;
|
||||||
|
_jsUnmarshalledRuntime = jsUnmarshalledRuntime;
|
||||||
|
_inputFileElement = inputFileElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await _jsRuntime.InvokeVoidAsync(InputFileInterop.EnsureArrayBufferReadyForSharedMemoryInterop, cancellationToken, _inputFileElement, File.Id);
|
||||||
|
|
||||||
|
var readRequest = new ReadRequest
|
||||||
|
{
|
||||||
|
InputFileElementReferenceId = _inputFileElement.Id,
|
||||||
|
FileId = File.Id,
|
||||||
|
SourceOffset = sourceOffset
|
||||||
|
};
|
||||||
|
|
||||||
|
if (MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArraySegment))
|
||||||
|
{
|
||||||
|
readRequest.Destination = destinationArraySegment.Array!;
|
||||||
|
readRequest.DestinationOffset = destinationArraySegment.Offset;
|
||||||
|
readRequest.MaxBytes = destinationArraySegment.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Worst case, we need to copy to a temporary array.
|
||||||
|
readRequest.Destination = new byte[destination.Length];
|
||||||
|
readRequest.DestinationOffset = 0;
|
||||||
|
readRequest.MaxBytes = destination.Length;
|
||||||
|
|
||||||
|
destination.CopyTo(new Memory<byte>(readRequest.Destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _jsUnmarshalledRuntime.InvokeUnmarshalled<ReadRequest, int>(InputFileInterop.ReadFileDataSharedMemory, readRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
// Exported functions
|
||||||
|
|
||||||
|
function init(callbackWrapper, elem) {
|
||||||
|
elem._blazorInputFileNextFileId = 0;
|
||||||
|
|
||||||
|
elem.addEventListener('click', function () {
|
||||||
|
// Permits replacing an existing file with a new one of the same file name.
|
||||||
|
elem.value = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
elem.addEventListener('change', function () {
|
||||||
|
// Reduce to purely serializable data, plus an index by ID.
|
||||||
|
elem._blazorFilesById = {};
|
||||||
|
|
||||||
|
const fileList = Array.prototype.map.call(elem.files, function (file) {
|
||||||
|
const result = {
|
||||||
|
id: ++elem._blazorInputFileNextFileId,
|
||||||
|
lastModified: new Date(file.lastModified).toISOString(),
|
||||||
|
name: file.name,
|
||||||
|
size: file.size,
|
||||||
|
type: file.type,
|
||||||
|
};
|
||||||
|
|
||||||
|
elem._blazorFilesById[result.id] = result;
|
||||||
|
|
||||||
|
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON.
|
||||||
|
Object.defineProperty(result, 'blob', { value: file });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
callbackWrapper.invokeMethodAsync('NotifyChange', fileList);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toImageFile(elem, fileId, format, maxWidth, maxHeight) {
|
||||||
|
var originalFile = getFileById(elem, fileId);
|
||||||
|
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
var originalFileImage = new Image();
|
||||||
|
originalFileImage.onload = function () { resolve(originalFileImage); };
|
||||||
|
originalFileImage.src = URL.createObjectURL(originalFile.blob);
|
||||||
|
}).then(function (loadedImage) {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
var desiredWidthRatio = Math.min(1, maxWidth / loadedImage.width);
|
||||||
|
var desiredHeightRatio = Math.min(1, maxHeight / loadedImage.height);
|
||||||
|
var chosenSizeRatio = Math.min(desiredWidthRatio, desiredHeightRatio);
|
||||||
|
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = Math.round(loadedImage.width * chosenSizeRatio);
|
||||||
|
canvas.height = Math.round(loadedImage.height * chosenSizeRatio);
|
||||||
|
canvas.getContext('2d').drawImage(loadedImage, 0, 0, canvas.width, canvas.height);
|
||||||
|
canvas.toBlob(resolve, format);
|
||||||
|
});
|
||||||
|
}).then(function (resizedImageBlob) {
|
||||||
|
var result = {
|
||||||
|
id: ++elem._blazorInputFileNextFileId,
|
||||||
|
lastModified: originalFile.lastModified,
|
||||||
|
name: originalFile.name, // Note: we're not changing the file extension.
|
||||||
|
size: resizedImageBlob.size,
|
||||||
|
type: format,
|
||||||
|
relativePath: originalFile.relativePath
|
||||||
|
};
|
||||||
|
|
||||||
|
elem._blazorFilesById[result.id] = result;
|
||||||
|
|
||||||
|
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON.
|
||||||
|
Object.defineProperty(result, 'blob', { value: resizedImageBlob });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureArrayBufferReadyForSharedMemoryInterop(elem, fileId) {
|
||||||
|
return getArrayBufferFromFileAsync(elem, fileId).then(function (arrayBuffer) {
|
||||||
|
getFileById(elem, fileId).arrayBuffer = arrayBuffer;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFileData(elem, fileId, startOffset, count) {
|
||||||
|
return getArrayBufferFromFileAsync(elem, fileId).then(function (arrayBuffer) {
|
||||||
|
return btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer, startOffset, count)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFileDataSharedMemory(readRequest) {
|
||||||
|
const inputFileElementReferenceId = Blazor.platform.readStringField(readRequest, 0);
|
||||||
|
const inputFileElement = document.querySelector(`[_bl_${inputFileElementReferenceId}]`);
|
||||||
|
const fileId = Blazor.platform.readInt32Field(readRequest, 4);
|
||||||
|
const sourceOffset = Blazor.platform.readUint64Field(readRequest, 8);
|
||||||
|
const destination = Blazor.platform.readInt32Field(readRequest, 16);
|
||||||
|
const destinationOffset = Blazor.platform.readInt32Field(readRequest, 20);
|
||||||
|
const maxBytes = Blazor.platform.readInt32Field(readRequest, 24);
|
||||||
|
|
||||||
|
const sourceArrayBuffer = getFileById(inputFileElement, fileId).arrayBuffer;
|
||||||
|
const bytesToRead = Math.min(maxBytes, sourceArrayBuffer.byteLength - sourceOffset);
|
||||||
|
const sourceUint8Array = new Uint8Array(sourceArrayBuffer, sourceOffset, bytesToRead);
|
||||||
|
|
||||||
|
const destinationUint8Array = Blazor.platform.toUint8Array(destination);
|
||||||
|
destinationUint8Array.set(sourceUint8Array, destinationOffset);
|
||||||
|
|
||||||
|
return bytesToRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local helpers
|
||||||
|
|
||||||
|
function getFileById(elem, fileId) {
|
||||||
|
const file = elem._blazorFilesById[fileId];
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
throw new Error(`There is no file with ID ${fileId}. The file list may have changed.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArrayBufferFromFileAsync(elem, fileId) {
|
||||||
|
const file = getFileById(elem, fileId);
|
||||||
|
|
||||||
|
// On the first read, convert the FileReader into a Promise<ArrayBuffer>.
|
||||||
|
if (!file.readPromise) {
|
||||||
|
file.readPromise = new Promise(function (resolve, reject) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function () { resolve(reader.result); };
|
||||||
|
reader.onerror = function (err) { reject(err); };
|
||||||
|
reader.readAsArrayBuffer(file.blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return file.readPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
window._blazorInputFile = {
|
||||||
|
init,
|
||||||
|
toImageFile,
|
||||||
|
ensureArrayBufferReadyForSharedMemoryInterop,
|
||||||
|
readFileData,
|
||||||
|
readFileDataSharedMemory,
|
||||||
|
};
|
||||||
|
})();
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -7,11 +7,12 @@ import { shouldAutoStart } from './BootCommon';
|
||||||
import { RenderQueue } from './Platform/Circuits/RenderQueue';
|
import { RenderQueue } from './Platform/Circuits/RenderQueue';
|
||||||
import { ConsoleLogger } from './Platform/Logging/Loggers';
|
import { ConsoleLogger } from './Platform/Logging/Loggers';
|
||||||
import { LogLevel, Logger } from './Platform/Logging/Logger';
|
import { LogLevel, Logger } from './Platform/Logging/Logger';
|
||||||
import { discoverComponents, CircuitDescriptor } from './Platform/Circuits/CircuitManager';
|
import { CircuitDescriptor } from './Platform/Circuits/CircuitManager';
|
||||||
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
||||||
import { resolveOptions, CircuitStartOptions } from './Platform/Circuits/CircuitStartOptions';
|
import { resolveOptions, CircuitStartOptions } from './Platform/Circuits/CircuitStartOptions';
|
||||||
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
|
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
|
||||||
import { attachRootComponentToLogicalElement } from './Rendering/Renderer';
|
import { attachRootComponentToLogicalElement } from './Rendering/Renderer';
|
||||||
|
import { discoverComponents, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
|
||||||
|
|
||||||
let renderingFailed = false;
|
let renderingFailed = false;
|
||||||
let started = false;
|
let started = false;
|
||||||
|
|
@ -29,7 +30,7 @@ async function boot(userOptions?: Partial<CircuitStartOptions>): Promise<void> {
|
||||||
options.reconnectionHandler = options.reconnectionHandler || window['Blazor'].defaultReconnectionHandler;
|
options.reconnectionHandler = options.reconnectionHandler || window['Blazor'].defaultReconnectionHandler;
|
||||||
logger.log(LogLevel.Information, 'Starting up blazor server-side application.');
|
logger.log(LogLevel.Information, 'Starting up blazor server-side application.');
|
||||||
|
|
||||||
const components = discoverComponents(document);
|
const components = discoverComponents(document, 'server') as ServerComponentDescriptor[];
|
||||||
const circuit = new CircuitDescriptor(components);
|
const circuit = new CircuitDescriptor(components);
|
||||||
|
|
||||||
const initialConnection = await initializeConnection(options, logger, circuit);
|
const initialConnection = await initializeConnection(options, logger, circuit);
|
||||||
|
|
@ -97,7 +98,7 @@ async function initializeConnection(options: CircuitStartOptions, logger: Logger
|
||||||
|
|
||||||
connection.on('JS.AttachComponent', (componentId, selector) => attachRootComponentToLogicalElement(0, circuit.resolveElement(selector), componentId));
|
connection.on('JS.AttachComponent', (componentId, selector) => attachRootComponentToLogicalElement(0, circuit.resolveElement(selector), componentId));
|
||||||
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
|
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.EndInvokeDotNet', (args: string) => DotNet.jsCallDispatcher.endInvokeDotNetFromJS(...(DotNet.parseJsonWithRevivers(args) as [string, boolean, unknown])));
|
||||||
|
|
||||||
const renderQueue = RenderQueue.getOrCreate(logger);
|
const renderQueue = RenderQueue.getOrCreate(logger);
|
||||||
connection.on('JS.RenderBatch', (batchId: number, batchData: Uint8Array) => {
|
connection.on('JS.RenderBatch', (batchId: number, batchData: Uint8Array) => {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { DotNet } from '@microsoft/dotnet-js-interop';
|
||||||
import './GlobalExports';
|
import './GlobalExports';
|
||||||
import * as Environment from './Environment';
|
import * as Environment from './Environment';
|
||||||
import { monoPlatform } from './Platform/Mono/MonoPlatform';
|
import { monoPlatform } from './Platform/Mono/MonoPlatform';
|
||||||
import { renderBatch, getRendererer } from './Rendering/Renderer';
|
import { renderBatch, getRendererer, attachRootComponentToElement, attachRootComponentToLogicalElement } from './Rendering/Renderer';
|
||||||
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
|
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
|
||||||
import { shouldAutoStart } from './BootCommon';
|
import { shouldAutoStart } from './BootCommon';
|
||||||
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
||||||
|
|
@ -11,6 +11,8 @@ import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader';
|
||||||
import { BootConfigResult } from './Platform/BootConfig';
|
import { BootConfigResult } from './Platform/BootConfig';
|
||||||
import { Pointer } from './Platform/Platform';
|
import { Pointer } from './Platform/Platform';
|
||||||
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
|
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
|
||||||
|
import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher';
|
||||||
|
import { discoverComponents, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
|
||||||
|
|
||||||
let started = false;
|
let started = false;
|
||||||
|
|
||||||
|
|
@ -32,6 +34,9 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Configure JS interop
|
||||||
|
window['Blazor']._internal.invokeJSFromDotNet = invokeJSFromDotNet;
|
||||||
|
|
||||||
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
||||||
const platform = Environment.setPlatform(monoPlatform);
|
const platform = Environment.setPlatform(monoPlatform);
|
||||||
window['Blazor'].platform = platform;
|
window['Blazor'].platform = platform;
|
||||||
|
|
@ -68,8 +73,31 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
||||||
const environment = options?.environment;
|
const environment = options?.environment;
|
||||||
|
|
||||||
// Fetch the resources and prepare the Mono runtime
|
// Fetch the resources and prepare the Mono runtime
|
||||||
const bootConfigResult = await BootConfigResult.initAsync(environment);
|
const bootConfigPromise = BootConfigResult.initAsync(environment);
|
||||||
|
|
||||||
|
// Leverage the time while we are loading boot.config.json from the network to discover any potentially registered component on
|
||||||
|
// the document.
|
||||||
|
const discoveredComponents = discoverComponents(document, 'webassembly') as WebAssemblyComponentDescriptor[];
|
||||||
|
const componentAttacher = new WebAssemblyComponentAttacher(discoveredComponents);
|
||||||
|
window['Blazor']._internal.registeredComponents = {
|
||||||
|
getRegisteredComponentsCount: () => componentAttacher.getCount(),
|
||||||
|
getId: (index) => componentAttacher.getId(index),
|
||||||
|
getAssembly: (id) => BINDING.js_string_to_mono_string(componentAttacher.getAssembly(id)),
|
||||||
|
getTypeName: (id) => BINDING.js_string_to_mono_string(componentAttacher.getTypeName(id)),
|
||||||
|
getParameterDefinitions: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterDefinitions(id) || ''),
|
||||||
|
getParameterValues: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterValues(id) || ''),
|
||||||
|
};
|
||||||
|
|
||||||
|
window['Blazor']._internal.attachRootComponentToElement = (selector, componentId, rendererId) => {
|
||||||
|
const element = componentAttacher.resolveRegisteredElement(selector);
|
||||||
|
if (!element) {
|
||||||
|
attachRootComponentToElement(selector, componentId, rendererId);
|
||||||
|
} else {
|
||||||
|
attachRootComponentToLogicalElement(rendererId, element, componentId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const bootConfigResult = await bootConfigPromise;
|
||||||
const [resourceLoader] = await Promise.all([
|
const [resourceLoader] = await Promise.all([
|
||||||
WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}),
|
WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}),
|
||||||
WebAssemblyConfigLoader.initAsync(bootConfigResult)]);
|
WebAssemblyConfigLoader.initAsync(bootConfigResult)]);
|
||||||
|
|
@ -84,6 +112,28 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
||||||
platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly);
|
platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any {
|
||||||
|
const functionIdentifier = monoPlatform.readStringField(callInfo, 0)!;
|
||||||
|
const resultType = monoPlatform.readInt32Field(callInfo, 4);
|
||||||
|
const marshalledCallArgsJson = monoPlatform.readStringField(callInfo, 8);
|
||||||
|
const targetInstanceId = monoPlatform.readUint64Field(callInfo, 20);
|
||||||
|
|
||||||
|
if (marshalledCallArgsJson !== null) {
|
||||||
|
const marshalledCallAsyncHandle = monoPlatform.readUint64Field(callInfo, 12);
|
||||||
|
|
||||||
|
if (marshalledCallAsyncHandle !== 0) {
|
||||||
|
DotNet.jsCallDispatcher.beginInvokeJSFromDotNet(marshalledCallAsyncHandle, functionIdentifier, marshalledCallArgsJson, resultType, targetInstanceId);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const resultJson = DotNet.jsCallDispatcher.invokeJSFromDotNet(functionIdentifier, marshalledCallArgsJson, resultType, targetInstanceId)!;
|
||||||
|
return resultJson === null ? 0 : BINDING.js_string_to_mono_string(resultJson);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const func = DotNet.jsCallDispatcher.findJSFunction(functionIdentifier, targetInstanceId);
|
||||||
|
return func.call(null, arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window['Blazor'].start = boot;
|
window['Blazor'].start = boot;
|
||||||
if (shouldAutoStart()) {
|
if (shouldAutoStart()) {
|
||||||
boot().catch(error => {
|
boot().catch(error => {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ window['Blazor'] = {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
|
|
||||||
_internal: {
|
_internal: {
|
||||||
attachRootComponentToElement,
|
|
||||||
navigationManager: navigationManagerInternalFunctions,
|
navigationManager: navigationManagerInternalFunctions,
|
||||||
domWrapper: domFunctions,
|
domWrapper: domFunctions,
|
||||||
Virtualize,
|
Virtualize,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import { internalFunctions as navigationManagerFunctions } from '../../Services/NavigationManager';
|
import { internalFunctions as navigationManagerFunctions } from '../../Services/NavigationManager';
|
||||||
import { toLogicalRootCommentElement, LogicalElement } from '../../Rendering/LogicalElements';
|
import { toLogicalRootCommentElement, LogicalElement } from '../../Rendering/LogicalElements';
|
||||||
|
import { ServerComponentDescriptor } from '../../Services/ComponentDescriptorDiscovery';
|
||||||
|
|
||||||
export class CircuitDescriptor {
|
export class CircuitDescriptor {
|
||||||
public circuitId?: string;
|
public circuitId?: string;
|
||||||
|
|
||||||
public components: ComponentDescriptor[];
|
public components: ServerComponentDescriptor[];
|
||||||
|
|
||||||
public constructor(components: ComponentDescriptor[]) {
|
public constructor(components: ServerComponentDescriptor[]) {
|
||||||
this.circuitId = undefined;
|
this.circuitId = undefined;
|
||||||
this.components = components;
|
this.components = components;
|
||||||
}
|
}
|
||||||
|
|
@ -54,221 +55,3 @@ export class CircuitDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ComponentMarker {
|
|
||||||
type: string;
|
|
||||||
sequence: number;
|
|
||||||
descriptor: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ComponentDescriptor {
|
|
||||||
public type: string;
|
|
||||||
|
|
||||||
public start: Node;
|
|
||||||
|
|
||||||
public end?: Node;
|
|
||||||
|
|
||||||
public sequence: number;
|
|
||||||
|
|
||||||
public descriptor: string;
|
|
||||||
|
|
||||||
public constructor(type: string, start: Node, end: Node | undefined, sequence: number, descriptor: string) {
|
|
||||||
this.type = type;
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
this.sequence = sequence;
|
|
||||||
this.descriptor = descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toRecord(): ComponentMarker {
|
|
||||||
const result = { type: this.type, sequence: this.sequence, descriptor: this.descriptor };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function discoverComponents(document: Document): ComponentDescriptor[] {
|
|
||||||
const componentComments = resolveComponentComments(document);
|
|
||||||
const discoveredComponents: ComponentDescriptor[] = [];
|
|
||||||
for (let i = 0; i < componentComments.length; i++) {
|
|
||||||
const componentComment = componentComments[i];
|
|
||||||
const entry = new ComponentDescriptor(
|
|
||||||
componentComment.type,
|
|
||||||
componentComment.start,
|
|
||||||
componentComment.end,
|
|
||||||
componentComment.sequence,
|
|
||||||
componentComment.descriptor,
|
|
||||||
);
|
|
||||||
|
|
||||||
discoveredComponents.push(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return discoveredComponents.sort((a, b) => a.sequence - b.sequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
interface ComponentComment {
|
|
||||||
type: 'server';
|
|
||||||
sequence: number;
|
|
||||||
descriptor: string;
|
|
||||||
start: Node;
|
|
||||||
end?: Node;
|
|
||||||
prerenderId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveComponentComments(node: Node): ComponentComment[] {
|
|
||||||
if (!node.hasChildNodes()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: ComponentComment[] = [];
|
|
||||||
const childNodeIterator = new ComponentCommentIterator(node.childNodes);
|
|
||||||
while (childNodeIterator.next() && childNodeIterator.currentElement) {
|
|
||||||
const componentComment = getComponentComment(childNodeIterator);
|
|
||||||
if (componentComment) {
|
|
||||||
result.push(componentComment);
|
|
||||||
} else {
|
|
||||||
const childResults = resolveComponentComments(childNodeIterator.currentElement);
|
|
||||||
for (let j = 0; j < childResults.length; j++) {
|
|
||||||
const childResult = childResults[j];
|
|
||||||
result.push(childResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const blazorCommentRegularExpression = /\W*Blazor:[^{]*(.*)$/;
|
|
||||||
|
|
||||||
function getComponentComment(commentNodeIterator: ComponentCommentIterator): ComponentComment | undefined {
|
|
||||||
const candidateStart = commentNodeIterator.currentElement;
|
|
||||||
|
|
||||||
if (!candidateStart || candidateStart.nodeType !== Node.COMMENT_NODE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (candidateStart.textContent) {
|
|
||||||
const componentStartComment = new RegExp(blazorCommentRegularExpression);
|
|
||||||
const definition = componentStartComment.exec(candidateStart.textContent);
|
|
||||||
const json = definition && definition[1];
|
|
||||||
|
|
||||||
if (json) {
|
|
||||||
try {
|
|
||||||
return createComponentComment(json, candidateStart, commentNodeIterator);
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(`Found malformed component comment at ${candidateStart.textContent}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createComponentComment(json: string, start: Node, iterator: ComponentCommentIterator): ComponentComment {
|
|
||||||
const payload = JSON.parse(json) as ComponentComment;
|
|
||||||
const { type, sequence, descriptor, prerenderId } = payload;
|
|
||||||
if (type !== 'server') {
|
|
||||||
throw new Error(`Invalid component type '${type}'.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!descriptor) {
|
|
||||||
throw new Error('descriptor must be defined when using a descriptor.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sequence === undefined) {
|
|
||||||
throw new Error('sequence must be defined when using a descriptor.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Number.isInteger(sequence)) {
|
|
||||||
throw new Error(`Error parsing the sequence '${sequence}' for component '${json}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!prerenderId) {
|
|
||||||
return {
|
|
||||||
type,
|
|
||||||
sequence: sequence,
|
|
||||||
descriptor,
|
|
||||||
start,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const end = getComponentEndComment(prerenderId, iterator);
|
|
||||||
if (!end) {
|
|
||||||
throw new Error(`Could not find an end component comment for '${start}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type,
|
|
||||||
sequence,
|
|
||||||
descriptor,
|
|
||||||
start,
|
|
||||||
prerenderId,
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getComponentEndComment(prerenderedId: string, iterator: ComponentCommentIterator): ChildNode | undefined {
|
|
||||||
while (iterator.next() && iterator.currentElement) {
|
|
||||||
const node = iterator.currentElement;
|
|
||||||
if (node.nodeType !== Node.COMMENT_NODE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!node.textContent) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const definition = new RegExp(blazorCommentRegularExpression).exec(node.textContent);
|
|
||||||
const json = definition && definition[1];
|
|
||||||
if (!json) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
validateEndComponentPayload(json, prerenderedId);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateEndComponentPayload(json: string, prerenderedId: string): void {
|
|
||||||
const payload = JSON.parse(json) as ComponentComment;
|
|
||||||
if (Object.keys(payload).length !== 1) {
|
|
||||||
throw new Error(`Invalid end of component comment: '${json}'`);
|
|
||||||
}
|
|
||||||
const prerenderedEndId = payload.prerenderId;
|
|
||||||
if (!prerenderedEndId) {
|
|
||||||
throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);
|
|
||||||
}
|
|
||||||
if (prerenderedEndId !== prerenderedId) {
|
|
||||||
throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderedId}', '${prerenderedEndId}'`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComponentCommentIterator {
|
|
||||||
|
|
||||||
private childNodes: NodeListOf<ChildNode>;
|
|
||||||
|
|
||||||
private currentIndex: number;
|
|
||||||
|
|
||||||
private length: number;
|
|
||||||
|
|
||||||
public currentElement: ChildNode | undefined;
|
|
||||||
|
|
||||||
public constructor(childNodes: NodeListOf<ChildNode>) {
|
|
||||||
this.childNodes = childNodes;
|
|
||||||
this.currentIndex = -1;
|
|
||||||
this.length = childNodes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public next(): boolean {
|
|
||||||
this.currentIndex++;
|
|
||||||
if (this.currentIndex < this.length) {
|
|
||||||
this.currentElement = this.childNodes[this.currentIndex];
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
this.currentElement = undefined;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ const defaultOptions: CircuitStartOptions = {
|
||||||
configureSignalR: (_) => { },
|
configureSignalR: (_) => { },
|
||||||
logLevel: LogLevel.Warning,
|
logLevel: LogLevel.Warning,
|
||||||
reconnectionOptions: {
|
reconnectionOptions: {
|
||||||
maxRetries: 5,
|
maxRetries: 8,
|
||||||
retryIntervalMilliseconds: 3000,
|
retryIntervalMilliseconds: 20000,
|
||||||
dialogId: 'components-reconnect-modal',
|
dialogId: 'components-reconnect-modal',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,12 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
|
|
||||||
reloadParagraph: HTMLParagraphElement;
|
reloadParagraph: HTMLParagraphElement;
|
||||||
|
|
||||||
constructor(dialogId: string, private readonly document: Document, private readonly logger: Logger) {
|
loader: HTMLDivElement;
|
||||||
|
|
||||||
|
constructor(dialogId: string, private readonly maxRetries: number, private readonly document: Document, private readonly logger: Logger) {
|
||||||
this.modal = this.document.createElement('div');
|
this.modal = this.document.createElement('div');
|
||||||
this.modal.id = dialogId;
|
this.modal.id = dialogId;
|
||||||
|
this.maxRetries = maxRetries;
|
||||||
|
|
||||||
const modalStyles = [
|
const modalStyles = [
|
||||||
'position: fixed',
|
'position: fixed',
|
||||||
|
|
@ -37,6 +40,9 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
this.message = this.modal.querySelector('h5')!;
|
this.message = this.modal.querySelector('h5')!;
|
||||||
this.button = this.modal.querySelector('button')!;
|
this.button = this.modal.querySelector('button')!;
|
||||||
this.reloadParagraph = this.modal.querySelector('p')!;
|
this.reloadParagraph = this.modal.querySelector('p')!;
|
||||||
|
this.loader = this.getLoader();
|
||||||
|
|
||||||
|
this.message.after(this.loader);
|
||||||
|
|
||||||
this.button.addEventListener('click', async () => {
|
this.button.addEventListener('click', async () => {
|
||||||
this.show();
|
this.show();
|
||||||
|
|
@ -65,6 +71,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
this.document.body.appendChild(this.modal);
|
this.document.body.appendChild(this.modal);
|
||||||
}
|
}
|
||||||
this.modal.style.display = 'block';
|
this.modal.style.display = 'block';
|
||||||
|
this.loader.style.display = 'inline-block';
|
||||||
this.button.style.display = 'none';
|
this.button.style.display = 'none';
|
||||||
this.reloadParagraph.style.display = 'none';
|
this.reloadParagraph.style.display = 'none';
|
||||||
this.message.textContent = 'Attempting to reconnect to the server...';
|
this.message.textContent = 'Attempting to reconnect to the server...';
|
||||||
|
|
@ -78,6 +85,10 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(currentAttempt: number): void {
|
||||||
|
this.message.textContent = `Attempting to reconnect to the server: ${currentAttempt} of ${this.maxRetries}`;
|
||||||
|
}
|
||||||
|
|
||||||
hide(): void {
|
hide(): void {
|
||||||
this.modal.style.display = 'none';
|
this.modal.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +96,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
failed(): void {
|
failed(): void {
|
||||||
this.button.style.display = 'block';
|
this.button.style.display = 'block';
|
||||||
this.reloadParagraph.style.display = 'none';
|
this.reloadParagraph.style.display = 'none';
|
||||||
|
this.loader.style.display = 'none';
|
||||||
this.message.innerHTML = 'Reconnection failed. Try <a href>reloading</a> the page if you\'re unable to reconnect.';
|
this.message.innerHTML = 'Reconnection failed. Try <a href>reloading</a> the page if you\'re unable to reconnect.';
|
||||||
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +104,32 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
||||||
rejected(): void {
|
rejected(): void {
|
||||||
this.button.style.display = 'none';
|
this.button.style.display = 'none';
|
||||||
this.reloadParagraph.style.display = 'none';
|
this.reloadParagraph.style.display = 'none';
|
||||||
|
this.loader.style.display = 'none';
|
||||||
this.message.innerHTML = 'Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.';
|
this.message.innerHTML = 'Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.';
|
||||||
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getLoader(): HTMLDivElement {
|
||||||
|
const loader = this.document.createElement('div');
|
||||||
|
|
||||||
|
const loaderStyles = [
|
||||||
|
'border: 0.3em solid #f3f3f3',
|
||||||
|
'border-top: 0.3em solid #3498db',
|
||||||
|
'border-radius: 50%',
|
||||||
|
'width: 2em',
|
||||||
|
'height: 2em',
|
||||||
|
'display: inline-block'
|
||||||
|
];
|
||||||
|
|
||||||
|
loader.style.cssText = loaderStyles.join(';');
|
||||||
|
loader.animate([
|
||||||
|
{ transform: 'rotate(0deg)' },
|
||||||
|
{ transform: 'rotate(360deg)' }
|
||||||
|
], {
|
||||||
|
duration: 2000,
|
||||||
|
iterations: Infinity
|
||||||
|
});
|
||||||
|
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ export class DefaultReconnectionHandler implements ReconnectionHandler {
|
||||||
if (!this._reconnectionDisplay) {
|
if (!this._reconnectionDisplay) {
|
||||||
const modal = document.getElementById(options.dialogId);
|
const modal = document.getElementById(options.dialogId);
|
||||||
this._reconnectionDisplay = modal
|
this._reconnectionDisplay = modal
|
||||||
? new UserSpecifiedDisplay(modal)
|
? new UserSpecifiedDisplay(modal, options.maxRetries, document)
|
||||||
: new DefaultReconnectDisplay(options.dialogId, document, this._logger);
|
: new DefaultReconnectDisplay(options.dialogId, options.maxRetries, document, this._logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._currentReconnectionProcess) {
|
if (!this._currentReconnectionProcess) {
|
||||||
|
|
@ -38,6 +38,8 @@ export class DefaultReconnectionHandler implements ReconnectionHandler {
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReconnectionProcess {
|
class ReconnectionProcess {
|
||||||
|
static readonly MaximumFirstRetryInterval = 3000;
|
||||||
|
|
||||||
readonly reconnectDisplay: ReconnectDisplay;
|
readonly reconnectDisplay: ReconnectDisplay;
|
||||||
isDisposed = false;
|
isDisposed = false;
|
||||||
|
|
||||||
|
|
@ -54,7 +56,13 @@ class ReconnectionProcess {
|
||||||
|
|
||||||
async attemptPeriodicReconnection(options: ReconnectionOptions) {
|
async attemptPeriodicReconnection(options: ReconnectionOptions) {
|
||||||
for (let i = 0; i < options.maxRetries; i++) {
|
for (let i = 0; i < options.maxRetries; i++) {
|
||||||
await this.delay(options.retryIntervalMilliseconds);
|
this.reconnectDisplay.update(i + 1);
|
||||||
|
|
||||||
|
const delayDuration = i == 0 && options.retryIntervalMilliseconds > ReconnectionProcess.MaximumFirstRetryInterval
|
||||||
|
? ReconnectionProcess.MaximumFirstRetryInterval
|
||||||
|
: options.retryIntervalMilliseconds;
|
||||||
|
await this.delay(delayDuration);
|
||||||
|
|
||||||
if (this.isDisposed) {
|
if (this.isDisposed) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
export interface ReconnectDisplay {
|
export interface ReconnectDisplay {
|
||||||
show(): void;
|
show(): void;
|
||||||
|
update(currentAttempt: number): void;
|
||||||
hide(): void;
|
hide(): void;
|
||||||
failed(): void;
|
failed(): void;
|
||||||
rejected(): void;
|
rejected(): void;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,18 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
|
||||||
|
|
||||||
static readonly RejectedClassName = 'components-reconnect-rejected';
|
static readonly RejectedClassName = 'components-reconnect-rejected';
|
||||||
|
|
||||||
constructor(private dialog: HTMLElement) {
|
static readonly MaxRetriesId = 'components-reconnect-max-retries';
|
||||||
|
|
||||||
|
static readonly CurrentAttemptId = 'components-reconnect-current-attempt';
|
||||||
|
|
||||||
|
constructor(private dialog: HTMLElement, private readonly maxRetries: number, private readonly document: Document) {
|
||||||
|
this.document = document;
|
||||||
|
|
||||||
|
const maxRetriesElement = this.document.getElementById(UserSpecifiedDisplay.MaxRetriesId);
|
||||||
|
|
||||||
|
if (maxRetriesElement) {
|
||||||
|
maxRetriesElement.innerText = this.maxRetries.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
show(): void {
|
show(): void {
|
||||||
|
|
@ -16,6 +27,14 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
|
||||||
this.dialog.classList.add(UserSpecifiedDisplay.ShowClassName);
|
this.dialog.classList.add(UserSpecifiedDisplay.ShowClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(currentAttempt: number): void {
|
||||||
|
const currentAttemptElement = this.document.getElementById(UserSpecifiedDisplay.CurrentAttemptId);
|
||||||
|
|
||||||
|
if (currentAttemptElement) {
|
||||||
|
currentAttemptElement.innerText = currentAttempt.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hide(): void {
|
hide(): void {
|
||||||
this.removeClasses();
|
this.removeClasses();
|
||||||
this.dialog.classList.add(UserSpecifiedDisplay.HideClassName);
|
this.dialog.classList.add(UserSpecifiedDisplay.HideClassName);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { LogicalElement, toLogicalRootCommentElement } from '../Rendering/LogicalElements';
|
||||||
|
import { WebAssemblyComponentDescriptor } from '../Services/ComponentDescriptorDiscovery';
|
||||||
|
|
||||||
|
export class WebAssemblyComponentAttacher {
|
||||||
|
public preregisteredComponents: WebAssemblyComponentDescriptor[];
|
||||||
|
|
||||||
|
private componentsById: { [index: number]: WebAssemblyComponentDescriptor };
|
||||||
|
|
||||||
|
public constructor(components: WebAssemblyComponentDescriptor[]) {
|
||||||
|
this.preregisteredComponents = components;
|
||||||
|
const componentsById = {};
|
||||||
|
for (let index = 0; index < components.length; index++) {
|
||||||
|
const component = components[index];
|
||||||
|
componentsById[component.id] = component;
|
||||||
|
}
|
||||||
|
this.componentsById = componentsById;
|
||||||
|
}
|
||||||
|
|
||||||
|
public resolveRegisteredElement(id: string): LogicalElement | undefined {
|
||||||
|
const parsedId = Number.parseInt(id);
|
||||||
|
if (!Number.isNaN(parsedId)) {
|
||||||
|
return toLogicalRootCommentElement(this.componentsById[parsedId].start as Comment, this.componentsById[parsedId].end as Comment);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParameterValues(id: number): string | undefined {
|
||||||
|
return this.componentsById[id].parameterValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParameterDefinitions(id: number): string | undefined {
|
||||||
|
return this.componentsById[id].parameterDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTypeName(id: number): string {
|
||||||
|
return this.componentsById[id].typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAssembly(id: number): string {
|
||||||
|
return this.componentsById[id].assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getId(index: number): number {
|
||||||
|
return this.preregisteredComponents[index].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCount(): number {
|
||||||
|
return this.preregisteredComponents.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,354 @@
|
||||||
|
export function discoverComponents(document: Document, type: 'webassembly' | 'server'): ServerComponentDescriptor[] | WebAssemblyComponentDescriptor[] {
|
||||||
|
switch (type){
|
||||||
|
case 'webassembly':
|
||||||
|
return discoverWebAssemblyComponents(document);
|
||||||
|
case 'server':
|
||||||
|
return discoverServerComponents(document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function discoverServerComponents(document: Document): ServerComponentDescriptor[] {
|
||||||
|
const componentComments = resolveComponentComments(document, 'server') as ServerComponentComment[];
|
||||||
|
const discoveredComponents: ServerComponentDescriptor[] = [];
|
||||||
|
for (let i = 0; i < componentComments.length; i++) {
|
||||||
|
const componentComment = componentComments[i];
|
||||||
|
const entry = new ServerComponentDescriptor(
|
||||||
|
componentComment.type,
|
||||||
|
componentComment.start,
|
||||||
|
componentComment.end,
|
||||||
|
componentComment.sequence,
|
||||||
|
componentComment.descriptor,
|
||||||
|
);
|
||||||
|
|
||||||
|
discoveredComponents.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return discoveredComponents.sort((a, b): number => a.sequence - b.sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
function discoverWebAssemblyComponents(document: Document): WebAssemblyComponentDescriptor[] {
|
||||||
|
const componentComments = resolveComponentComments(document, 'webassembly') as WebAssemblyComponentDescriptor[];
|
||||||
|
const discoveredComponents: WebAssemblyComponentDescriptor[] = [];
|
||||||
|
for (let i = 0; i < componentComments.length; i++) {
|
||||||
|
const componentComment = componentComments[i];
|
||||||
|
const entry = new WebAssemblyComponentDescriptor(
|
||||||
|
componentComment.type,
|
||||||
|
componentComment.start,
|
||||||
|
componentComment.end,
|
||||||
|
componentComment.assembly,
|
||||||
|
componentComment.typeName,
|
||||||
|
componentComment.parameterDefinitions,
|
||||||
|
componentComment.parameterValues,
|
||||||
|
);
|
||||||
|
|
||||||
|
discoveredComponents.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return discoveredComponents.sort((a, b): number => a.id - b.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComponentComment {
|
||||||
|
type: 'server' | 'webassembly';
|
||||||
|
prerenderId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ServerComponentComment {
|
||||||
|
type: 'server';
|
||||||
|
sequence: number;
|
||||||
|
descriptor: string;
|
||||||
|
start: Node;
|
||||||
|
end?: Node;
|
||||||
|
prerenderId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WebAssemblyComponentComment {
|
||||||
|
type: 'webassembly';
|
||||||
|
typeName: string;
|
||||||
|
assembly: string;
|
||||||
|
parameterDefinitions?: string;
|
||||||
|
parameterValues?: string;
|
||||||
|
prerenderId?: string;
|
||||||
|
start: Node;
|
||||||
|
end?: Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveComponentComments(node: Node, type: 'webassembly' | 'server'): ComponentComment[] {
|
||||||
|
if (!node.hasChildNodes()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: ComponentComment[] = [];
|
||||||
|
const childNodeIterator = new ComponentCommentIterator(node.childNodes);
|
||||||
|
while (childNodeIterator.next() && childNodeIterator.currentElement) {
|
||||||
|
const componentComment = getComponentComment(childNodeIterator, type);
|
||||||
|
if (componentComment) {
|
||||||
|
result.push(componentComment);
|
||||||
|
} else {
|
||||||
|
const childResults = resolveComponentComments(childNodeIterator.currentElement, type);
|
||||||
|
for (let j = 0; j < childResults.length; j++) {
|
||||||
|
const childResult = childResults[j];
|
||||||
|
result.push(childResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const blazorCommentRegularExpression = /\W*Blazor:[^{]*(?<descriptor>.*)$/;
|
||||||
|
|
||||||
|
function getComponentComment(commentNodeIterator: ComponentCommentIterator, type: 'webassembly' | 'server'): ComponentComment | undefined {
|
||||||
|
const candidateStart = commentNodeIterator.currentElement;
|
||||||
|
|
||||||
|
if (!candidateStart || candidateStart.nodeType !== Node.COMMENT_NODE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (candidateStart.textContent) {
|
||||||
|
const componentStartComment = new RegExp(blazorCommentRegularExpression);
|
||||||
|
const definition = componentStartComment.exec(candidateStart.textContent);
|
||||||
|
const json = definition && definition.groups && definition.groups['descriptor'];
|
||||||
|
|
||||||
|
if (json) {
|
||||||
|
try {
|
||||||
|
const componentComment = parseCommentPayload(json);
|
||||||
|
switch (type) {
|
||||||
|
case 'webassembly':
|
||||||
|
return createWebAssemblyComponentComment(componentComment as WebAssemblyComponentComment, candidateStart, commentNodeIterator);
|
||||||
|
case 'server':
|
||||||
|
return createServerComponentComment(componentComment as ServerComponentComment, candidateStart, commentNodeIterator);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Found malformed component comment at ${candidateStart.textContent}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCommentPayload(json: string): ComponentComment {
|
||||||
|
const payload = JSON.parse(json) as ComponentComment;
|
||||||
|
const { type } = payload;
|
||||||
|
if (type !== 'server' && type !== 'webassembly') {
|
||||||
|
throw new Error(`Invalid component type '${type}'.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createServerComponentComment(payload: ServerComponentComment, start: Node, iterator: ComponentCommentIterator): ServerComponentComment | undefined {
|
||||||
|
const { type, descriptor, sequence, prerenderId } = payload;
|
||||||
|
if (type !== 'server') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!descriptor) {
|
||||||
|
throw new Error('descriptor must be defined when using a descriptor.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sequence === undefined) {
|
||||||
|
throw new Error('sequence must be defined when using a descriptor.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(sequence)) {
|
||||||
|
throw new Error(`Error parsing the sequence '${sequence}' for component '${JSON.stringify(payload)}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prerenderId) {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
sequence: sequence,
|
||||||
|
descriptor,
|
||||||
|
start,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const end = getComponentEndComment(prerenderId, iterator);
|
||||||
|
if (!end) {
|
||||||
|
throw new Error(`Could not find an end component comment for '${start}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
sequence,
|
||||||
|
descriptor,
|
||||||
|
start,
|
||||||
|
prerenderId,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWebAssemblyComponentComment(payload: WebAssemblyComponentComment, start: Node, iterator: ComponentCommentIterator): WebAssemblyComponentComment | undefined {
|
||||||
|
const { type, assembly, typeName, parameterDefinitions, parameterValues, prerenderId } = payload;
|
||||||
|
if (type !== 'webassembly') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assembly) {
|
||||||
|
throw new Error('assembly must be defined when using a descriptor.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!typeName) {
|
||||||
|
throw new Error('typeName must be defined when using a descriptor.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prerenderId) {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
assembly,
|
||||||
|
typeName,
|
||||||
|
// Parameter definitions and values come Base64 encoded from the server, since they contain random data and can make the
|
||||||
|
// comment invalid. We could unencode them in .NET Code, but that would be slower to do and we can leverage the fact that
|
||||||
|
// JS provides a native function that will be much faster and that we are doing this work while we are fetching
|
||||||
|
// blazor.boot.json
|
||||||
|
parameterDefinitions: parameterDefinitions && atob(parameterDefinitions),
|
||||||
|
parameterValues: parameterValues && atob(parameterValues),
|
||||||
|
start,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const end = getComponentEndComment(prerenderId, iterator);
|
||||||
|
if (!end) {
|
||||||
|
throw new Error(`Could not find an end component comment for '${start}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
assembly,
|
||||||
|
typeName,
|
||||||
|
// Same comment as above.
|
||||||
|
parameterDefinitions: parameterDefinitions && atob(parameterDefinitions),
|
||||||
|
parameterValues: parameterValues && atob(parameterValues),
|
||||||
|
start,
|
||||||
|
prerenderId,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComponentEndComment(prerenderedId: string, iterator: ComponentCommentIterator): ChildNode | undefined {
|
||||||
|
while (iterator.next() && iterator.currentElement) {
|
||||||
|
const node = iterator.currentElement;
|
||||||
|
if (node.nodeType !== Node.COMMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!node.textContent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = new RegExp(blazorCommentRegularExpression).exec(node.textContent);
|
||||||
|
const json = definition && definition[1];
|
||||||
|
if (!json) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateEndComponentPayload(json, prerenderedId);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateEndComponentPayload(json: string, prerenderedId: string): void {
|
||||||
|
const payload = JSON.parse(json) as ComponentComment;
|
||||||
|
if (Object.keys(payload).length !== 1) {
|
||||||
|
throw new Error(`Invalid end of component comment: '${json}'`);
|
||||||
|
}
|
||||||
|
const prerenderedEndId = payload.prerenderId;
|
||||||
|
if (!prerenderedEndId) {
|
||||||
|
throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);
|
||||||
|
}
|
||||||
|
if (prerenderedEndId !== prerenderedId) {
|
||||||
|
throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderedId}', '${prerenderedEndId}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ComponentCommentIterator {
|
||||||
|
|
||||||
|
private childNodes: NodeListOf<ChildNode>;
|
||||||
|
|
||||||
|
private currentIndex: number;
|
||||||
|
|
||||||
|
private length: number;
|
||||||
|
|
||||||
|
public currentElement: ChildNode | undefined;
|
||||||
|
|
||||||
|
public constructor(childNodes: NodeListOf<ChildNode>) {
|
||||||
|
this.childNodes = childNodes;
|
||||||
|
this.currentIndex = -1;
|
||||||
|
this.length = childNodes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public next(): boolean {
|
||||||
|
this.currentIndex++;
|
||||||
|
if (this.currentIndex < this.length) {
|
||||||
|
this.currentElement = this.childNodes[this.currentIndex];
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.currentElement = undefined;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ServerComponentMarker {
|
||||||
|
type: string;
|
||||||
|
sequence: number;
|
||||||
|
descriptor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ServerComponentDescriptor {
|
||||||
|
public type: string;
|
||||||
|
|
||||||
|
public start: Node;
|
||||||
|
|
||||||
|
public end?: Node;
|
||||||
|
|
||||||
|
public sequence: number;
|
||||||
|
|
||||||
|
public descriptor: string;
|
||||||
|
|
||||||
|
public constructor(type: string, start: Node, end: Node | undefined, sequence: number, descriptor: string) {
|
||||||
|
this.type = type;
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.sequence = sequence;
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toRecord(): ServerComponentMarker {
|
||||||
|
const result = { type: this.type, sequence: this.sequence, descriptor: this.descriptor };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WebAssemblyComponentDescriptor {
|
||||||
|
private static globalId = 1;
|
||||||
|
|
||||||
|
public type: 'webassembly';
|
||||||
|
|
||||||
|
public typeName: string;
|
||||||
|
|
||||||
|
public assembly: string;
|
||||||
|
|
||||||
|
public parameterDefinitions?: string;
|
||||||
|
|
||||||
|
public parameterValues?: string;
|
||||||
|
|
||||||
|
public id: number;
|
||||||
|
|
||||||
|
public start: Node;
|
||||||
|
|
||||||
|
public end?: Node;
|
||||||
|
|
||||||
|
public constructor(type: 'webassembly', start: Node, end: Node | undefined, assembly: string, typeName: string, parameterDefinitions?: string, parameterValues?: string) {
|
||||||
|
this.id = WebAssemblyComponentDescriptor.globalId++;
|
||||||
|
this.type = type;
|
||||||
|
this.assembly = assembly;
|
||||||
|
this.typeName = typeName;
|
||||||
|
this.parameterDefinitions = parameterDefinitions;
|
||||||
|
this.parameterValues = parameterValues;
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -57,15 +57,16 @@ function init(dotNetHelper: any, spacerBefore: HTMLElement, spacerAfter: HTMLEle
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const spacerSeparation = spacerAfter.offsetTop - (spacerBefore.offsetTop + spacerBefore.offsetHeight);
|
||||||
const containerSize = entry.rootBounds?.height;
|
const containerSize = entry.rootBounds?.height;
|
||||||
|
|
||||||
if (entry.target === spacerBefore) {
|
if (entry.target === spacerBefore) {
|
||||||
dotNetHelper.invokeMethodAsync('OnSpacerBeforeVisible', entry.intersectionRect.top - entry.boundingClientRect.top, containerSize);
|
dotNetHelper.invokeMethodAsync('OnSpacerBeforeVisible', entry.intersectionRect.top - entry.boundingClientRect.top, spacerSeparation, containerSize);
|
||||||
} else if (entry.target === spacerAfter && spacerAfter.offsetHeight > 0) {
|
} else if (entry.target === spacerAfter && spacerAfter.offsetHeight > 0) {
|
||||||
// When we first start up, both the "before" and "after" spacers will be visible, but it's only relevant to raise a
|
// When we first start up, both the "before" and "after" spacers will be visible, but it's only relevant to raise a
|
||||||
// single event to load the initial data. To avoid raising two events, skip the one for the "after" spacer if we know
|
// single event to load the initial data. To avoid raising two events, skip the one for the "after" spacer if we know
|
||||||
// it's meaningless to talk about any overlap into it.
|
// it's meaningless to talk about any overlap into it.
|
||||||
dotNetHelper.invokeMethodAsync('OnSpacerAfterVisible', entry.boundingClientRect.bottom - entry.intersectionRect.bottom, containerSize);
|
dotNetHelper.invokeMethodAsync('OnSpacerAfterVisible', entry.boundingClientRect.bottom - entry.intersectionRect.bottom, spacerSeparation, containerSize);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,18 @@ import { JSDOM } from 'jsdom';
|
||||||
import { NullLogger } from '../src/Platform/Logging/Loggers';
|
import { NullLogger } from '../src/Platform/Logging/Loggers';
|
||||||
|
|
||||||
describe('DefaultReconnectDisplay', () => {
|
describe('DefaultReconnectDisplay', () => {
|
||||||
|
let testDocument: Document;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const window = new JSDOM().window;
|
||||||
|
|
||||||
|
//JSDOM does not support animate function so we need to mock it
|
||||||
|
window.HTMLDivElement.prototype.animate = jest.fn();
|
||||||
|
testDocument = window.document;
|
||||||
|
})
|
||||||
|
|
||||||
it ('adds element to the body on show', () => {
|
it ('adds element to the body on show', () => {
|
||||||
const testDocument = new JSDOM().window.document;
|
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
|
||||||
|
|
||||||
display.show();
|
display.show();
|
||||||
|
|
||||||
|
|
@ -16,6 +24,7 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
expect(element!.style.display).toBe('block');
|
expect(element!.style.display).toBe('block');
|
||||||
expect(element!.style.visibility).toBe('hidden');
|
expect(element!.style.visibility).toBe('hidden');
|
||||||
|
|
||||||
|
expect(display.loader.style.display).toBe('inline-block');
|
||||||
expect(display.message.textContent).toBe('Attempting to reconnect to the server...');
|
expect(display.message.textContent).toBe('Attempting to reconnect to the server...');
|
||||||
expect(display.button.style.display).toBe('none');
|
expect(display.button.style.display).toBe('none');
|
||||||
|
|
||||||
|
|
@ -27,8 +36,7 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('does not add element to the body multiple times', () => {
|
it ('does not add element to the body multiple times', () => {
|
||||||
const testDocument = new JSDOM().window.document;
|
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
|
||||||
|
|
||||||
display.show();
|
display.show();
|
||||||
display.show();
|
display.show();
|
||||||
|
|
@ -37,8 +45,7 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('hides element', () => {
|
it ('hides element', () => {
|
||||||
const testDocument = new JSDOM().window.document;
|
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
|
||||||
|
|
||||||
display.hide();
|
display.hide();
|
||||||
|
|
||||||
|
|
@ -46,8 +53,7 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('updates message on fail', () => {
|
it ('updates message on fail', () => {
|
||||||
const testDocument = new JSDOM().window.document;
|
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
|
||||||
|
|
||||||
display.show();
|
display.show();
|
||||||
display.failed();
|
display.failed();
|
||||||
|
|
@ -55,11 +61,11 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
expect(display.modal.style.display).toBe('block');
|
expect(display.modal.style.display).toBe('block');
|
||||||
expect(display.message.innerHTML).toBe('Reconnection failed. Try <a href=\"\">reloading</a> the page if you\'re unable to reconnect.');
|
expect(display.message.innerHTML).toBe('Reconnection failed. Try <a href=\"\">reloading</a> the page if you\'re unable to reconnect.');
|
||||||
expect(display.button.style.display).toBe('block');
|
expect(display.button.style.display).toBe('block');
|
||||||
|
expect(display.loader.style.display).toBe('none');
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('updates message on refused', () => {
|
it ('updates message on refused', () => {
|
||||||
const testDocument = new JSDOM().window.document;
|
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
|
||||||
|
|
||||||
display.show();
|
display.show();
|
||||||
display.rejected();
|
display.rejected();
|
||||||
|
|
@ -67,6 +73,18 @@ describe('DefaultReconnectDisplay', () => {
|
||||||
expect(display.modal.style.display).toBe('block');
|
expect(display.modal.style.display).toBe('block');
|
||||||
expect(display.message.innerHTML).toBe('Could not reconnect to the server. <a href=\"\">Reload</a> the page to restore functionality.');
|
expect(display.message.innerHTML).toBe('Could not reconnect to the server. <a href=\"\">Reload</a> the page to restore functionality.');
|
||||||
expect(display.button.style.display).toBe('none');
|
expect(display.button.style.display).toBe('none');
|
||||||
|
expect(display.loader.style.display).toBe('none');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('update message with current attempt', () => {
|
||||||
|
const maxRetires = 6;
|
||||||
|
const display = new DefaultReconnectDisplay('test-dialog-id', maxRetires, testDocument, NullLogger.instance);
|
||||||
|
|
||||||
|
display.show();
|
||||||
|
|
||||||
|
for (let index = 0; index < maxRetires; index++) {
|
||||||
|
display.update(index);
|
||||||
|
expect(display.message.innerHTML).toBe(`Attempting to reconnect to the server: ${index++} of ${maxRetires}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,23 @@ describe('DefaultReconnectionHandler', () => {
|
||||||
expect(testDisplay.failed).toHaveBeenCalled();
|
expect(testDisplay.failed).toHaveBeenCalled();
|
||||||
expect(reconnect).toHaveBeenCalledTimes(2);
|
expect(reconnect).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('invokes update on each attempt', async () => {
|
||||||
|
const testDisplay = createTestDisplay();
|
||||||
|
const reconnect = jest.fn().mockRejectedValue(null);
|
||||||
|
const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
|
||||||
|
const maxRetries = 6;
|
||||||
|
|
||||||
|
handler.onConnectionDown({
|
||||||
|
maxRetries: maxRetries,
|
||||||
|
retryIntervalMilliseconds: 5,
|
||||||
|
dialogId: 'ignored'
|
||||||
|
});
|
||||||
|
|
||||||
|
await delay(500);
|
||||||
|
expect(testDisplay.update).toHaveBeenCalledTimes(maxRetries);
|
||||||
|
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
function attachUserSpecifiedUI(options: ReconnectionOptions): Element {
|
function attachUserSpecifiedUI(options: ReconnectionOptions): Element {
|
||||||
|
|
@ -92,6 +109,7 @@ function delay(durationMilliseconds: number) {
|
||||||
function createTestDisplay(): ReconnectDisplay {
|
function createTestDisplay(): ReconnectDisplay {
|
||||||
return {
|
return {
|
||||||
show: jest.fn(),
|
show: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
hide: jest.fn(),
|
hide: jest.fn(),
|
||||||
failed: jest.fn(),
|
failed: jest.fn(),
|
||||||
rejected: jest.fn()
|
rejected: jest.fn()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.Forms
|
namespace Microsoft.AspNetCore.Components.Forms
|
||||||
|
|
@ -13,6 +12,8 @@ namespace Microsoft.AspNetCore.Components.Forms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class EditContextFieldClassExtensions
|
public static class EditContextFieldClassExtensions
|
||||||
{
|
{
|
||||||
|
private readonly static object FieldCssClassProviderKey = new object();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a string that indicates the status of the specified field as a CSS class. 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.
|
/// some combination of "modified", "valid", or "invalid", depending on the status of the field.
|
||||||
|
|
@ -24,23 +25,34 @@ namespace Microsoft.AspNetCore.Components.Forms
|
||||||
=> FieldCssClass(editContext, FieldIdentifier.Create(accessor));
|
=> FieldCssClass(editContext, FieldIdentifier.Create(accessor));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a string that indicates the status of the specified field as a CSS class. This will include
|
/// Gets a string that indicates the status of the specified field as a CSS class.
|
||||||
/// some combination of "modified", "valid", or "invalid", depending on the status of the field.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||||
/// <param name="fieldIdentifier">An identifier for the field.</param>
|
/// <param name="fieldIdentifier">An identifier for the field.</param>
|
||||||
/// <returns>A string that indicates the status of the field.</returns>
|
/// <returns>A string that indicates the status of the field.</returns>
|
||||||
public static string FieldCssClass(this EditContext editContext, in FieldIdentifier fieldIdentifier)
|
public static string FieldCssClass(this EditContext editContext, in FieldIdentifier fieldIdentifier)
|
||||||
{
|
{
|
||||||
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
|
var provider = editContext.Properties.TryGetValue(FieldCssClassProviderKey, out var customProvider)
|
||||||
if (editContext.IsModified(fieldIdentifier))
|
? (FieldCssClassProvider)customProvider
|
||||||
|
: FieldCssClassProvider.Instance;
|
||||||
|
|
||||||
|
return provider.GetFieldCssClass(editContext, fieldIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Associates the supplied <see cref="FieldCssClassProvider"/> with the supplied <see cref="EditContext"/>.
|
||||||
|
/// This customizes the field CSS class names used within the <see cref="EditContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||||
|
/// <param name="fieldCssClassProvider">The <see cref="FieldCssClassProvider"/>.</param>
|
||||||
|
public static void SetFieldCssClassProvider(this EditContext editContext, FieldCssClassProvider fieldCssClassProvider)
|
||||||
|
{
|
||||||
|
if (fieldCssClassProvider is null)
|
||||||
{
|
{
|
||||||
return isValid ? "modified valid" : "modified invalid";
|
throw new ArgumentNullException(nameof(fieldCssClassProvider));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return isValid ? "valid" : "invalid";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editContext.Properties[FieldCssClassProviderKey] = fieldCssClassProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.Forms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Supplies CSS class names for form fields to represent their validation state or other
|
||||||
|
/// state information from an <see cref="EditContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class FieldCssClassProvider
|
||||||
|
{
|
||||||
|
internal readonly static FieldCssClassProvider Instance = new FieldCssClassProvider();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string that indicates the status of the specified field as a CSS class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||||
|
/// <param name="fieldIdentifier">The <see cref="FieldIdentifier"/>.</param>
|
||||||
|
/// <returns>A CSS class name string.</returns>
|
||||||
|
public virtual string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
|
||||||
|
{
|
||||||
|
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
|
||||||
|
if (editContext.IsModified(fieldIdentifier))
|
||||||
|
{
|
||||||
|
return isValid ? "modified valid" : "modified invalid";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return isValid ? "valid" : "invalid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
{
|
{
|
||||||
internal interface IVirtualizeJsCallbacks
|
internal interface IVirtualizeJsCallbacks
|
||||||
{
|
{
|
||||||
void OnBeforeSpacerVisible(float spacerSize, float containerSize);
|
void OnBeforeSpacerVisible(float spacerSize, float spacerSeparation, float containerSize);
|
||||||
void OnAfterSpacerVisible(float spacerSize, float containerSize);
|
void OnAfterSpacerVisible(float spacerSize, float spacerSeparation, float containerSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,24 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Index { get; }
|
public int Index { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the placeholder in pixels.
|
||||||
|
/// <para>
|
||||||
|
/// For virtualized components with vertical scrolling, this would be the height of the placeholder in pixels.
|
||||||
|
/// For virtualized components with horizontal scrolling, this would be the width of the placeholder in pixels.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public float Size { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new <see cref="PlaceholderContext"/> instance.
|
/// Constructs a new <see cref="PlaceholderContext"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The item index of the placeholder.</param>
|
/// <param name="index">The item index of the placeholder.</param>
|
||||||
public PlaceholderContext(int index)
|
/// <param name="size">The size of the placeholder in pixels.</param>
|
||||||
|
public PlaceholderContext(int index, float size = 0f)
|
||||||
{
|
{
|
||||||
Index = index;
|
Index = index;
|
||||||
|
Size = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
|
|
||||||
private int _loadedItemsStartIndex;
|
private int _loadedItemsStartIndex;
|
||||||
|
|
||||||
|
private int _lastRenderedItemCount;
|
||||||
|
|
||||||
|
private int _lastRenderedPlaceholderCount;
|
||||||
|
|
||||||
|
private float _itemSize;
|
||||||
|
|
||||||
private IEnumerable<TItem>? _loadedItems;
|
private IEnumerable<TItem>? _loadedItems;
|
||||||
|
|
||||||
private CancellationTokenSource? _refreshCts;
|
private CancellationTokenSource? _refreshCts;
|
||||||
|
|
@ -65,10 +71,10 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
public RenderFragment<PlaceholderContext>? Placeholder { get; set; }
|
public RenderFragment<PlaceholderContext>? Placeholder { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the size of each item in pixels.
|
/// Gets the size of each item in pixels. Defaults to 50px.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public float ItemSize { get; set; }
|
public float ItemSize { get; set; } = 50f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the function providing items to the list.
|
/// Gets or sets the function providing items to the list.
|
||||||
|
|
@ -88,7 +94,12 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
if (ItemSize <= 0)
|
if (ItemSize <= 0)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
$"{GetType()} requires a positive value for parameter '{nameof(ItemSize)}' to perform virtualization.");
|
$"{GetType()} requires a positive value for parameter '{nameof(ItemSize)}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_itemSize <= 0)
|
||||||
|
{
|
||||||
|
_itemSize = ItemSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ItemsProvider != null)
|
if (ItemsProvider != null)
|
||||||
|
|
@ -154,11 +165,13 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
{
|
{
|
||||||
// This is a rare case where it's valid for the sequence number to be programmatically incremented.
|
// This is a rare case where it's valid for the sequence number to be programmatically incremented.
|
||||||
// This is only true because we know for certain that no other content will be alongside it.
|
// This is only true because we know for certain that no other content will be alongside it.
|
||||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex, _itemSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.CloseRegion();
|
builder.CloseRegion();
|
||||||
|
|
||||||
|
_lastRenderedItemCount = 0;
|
||||||
|
|
||||||
// Render the loaded items.
|
// Render the loaded items.
|
||||||
if (_loadedItems != null && _itemTemplate != null)
|
if (_loadedItems != null && _itemTemplate != null)
|
||||||
{
|
{
|
||||||
|
|
@ -171,18 +184,22 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
foreach (var item in itemsToShow)
|
foreach (var item in itemsToShow)
|
||||||
{
|
{
|
||||||
_itemTemplate(item)(builder);
|
_itemTemplate(item)(builder);
|
||||||
renderIndex++;
|
_lastRenderedItemCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderIndex += _lastRenderedItemCount;
|
||||||
|
|
||||||
builder.CloseRegion();
|
builder.CloseRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastRenderedPlaceholderCount = Math.Max(0, lastItemIndex - _itemsBefore - _lastRenderedItemCount);
|
||||||
|
|
||||||
builder.OpenRegion(5);
|
builder.OpenRegion(5);
|
||||||
|
|
||||||
// Render the placeholders after the loaded items.
|
// Render the placeholders after the loaded items.
|
||||||
for (; renderIndex < lastItemIndex; renderIndex++)
|
for (; renderIndex < lastItemIndex; renderIndex++)
|
||||||
{
|
{
|
||||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex, _itemSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.CloseRegion();
|
builder.CloseRegion();
|
||||||
|
|
@ -197,28 +214,45 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetSpacerStyle(int itemsInSpacer)
|
private string GetSpacerStyle(int itemsInSpacer)
|
||||||
=> $"height: {itemsInSpacer * ItemSize}px;";
|
=> $"height: {itemsInSpacer * _itemSize}px;";
|
||||||
|
|
||||||
void IVirtualizeJsCallbacks.OnBeforeSpacerVisible(float spacerSize, float containerSize)
|
void IVirtualizeJsCallbacks.OnBeforeSpacerVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||||
{
|
{
|
||||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsBefore, out var visibleItemCapacity);
|
CalcualteItemDistribution(spacerSize, spacerSeparation, containerSize, out var itemsBefore, out var visibleItemCapacity);
|
||||||
|
|
||||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVirtualizeJsCallbacks.OnAfterSpacerVisible(float spacerSize, float containerSize)
|
void IVirtualizeJsCallbacks.OnAfterSpacerVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||||
{
|
{
|
||||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsAfter, out var visibleItemCapacity);
|
CalcualteItemDistribution(spacerSize, spacerSeparation, containerSize, out var itemsAfter, out var visibleItemCapacity);
|
||||||
|
|
||||||
var itemsBefore = Math.Max(0, _itemCount - itemsAfter - visibleItemCapacity);
|
var itemsBefore = Math.Max(0, _itemCount - itemsAfter - visibleItemCapacity);
|
||||||
|
|
||||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CalcualteItemDistribution(float spacerSize, float containerSize, out int itemsInSpacer, out int visibleItemCapacity)
|
private void CalcualteItemDistribution(
|
||||||
|
float spacerSize,
|
||||||
|
float spacerSeparation,
|
||||||
|
float containerSize,
|
||||||
|
out int itemsInSpacer,
|
||||||
|
out int visibleItemCapacity)
|
||||||
{
|
{
|
||||||
itemsInSpacer = Math.Max(0, (int)Math.Floor(spacerSize / ItemSize) - 1);
|
if (_lastRenderedItemCount > 0)
|
||||||
visibleItemCapacity = (int)Math.Ceiling(containerSize / ItemSize) + 2;
|
{
|
||||||
|
_itemSize = (spacerSeparation - (_lastRenderedPlaceholderCount * _itemSize)) / _lastRenderedItemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_itemSize <= 0)
|
||||||
|
{
|
||||||
|
// At this point, something unusual has occurred, likely due to misuse of this component.
|
||||||
|
// Reset the calculated item size to the user-provided item size.
|
||||||
|
_itemSize = ItemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsInSpacer = Math.Max(0, (int)Math.Floor(spacerSize / _itemSize) - 1);
|
||||||
|
visibleItemCapacity = (int)Math.Ceiling(containerSize / _itemSize) + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateItemDistribution(int itemsBefore, int visibleItemCapacity)
|
private void UpdateItemDistribution(int itemsBefore, int visibleItemCapacity)
|
||||||
|
|
@ -285,7 +319,7 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
private RenderFragment DefaultPlaceholder(PlaceholderContext context) => (builder) =>
|
private RenderFragment DefaultPlaceholder(PlaceholderContext context) => (builder) =>
|
||||||
{
|
{
|
||||||
builder.OpenElement(0, "div");
|
builder.OpenElement(0, "div");
|
||||||
builder.AddAttribute(1, "style", $"height: {ItemSize}px;");
|
builder.AddAttribute(1, "style", $"height: {_itemSize}px;");
|
||||||
builder.CloseElement();
|
builder.CloseElement();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,15 +30,15 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
}
|
}
|
||||||
|
|
||||||
[JSInvokable]
|
[JSInvokable]
|
||||||
public void OnSpacerBeforeVisible(float spacerSize, float containerSize)
|
public void OnSpacerBeforeVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||||
{
|
{
|
||||||
_owner.OnBeforeSpacerVisible(spacerSize, containerSize);
|
_owner.OnBeforeSpacerVisible(spacerSize, spacerSeparation, containerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
[JSInvokable]
|
[JSInvokable]
|
||||||
public void OnSpacerAfterVisible(float spacerSize, float containerSize)
|
public void OnSpacerAfterVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||||
{
|
{
|
||||||
_owner.OnAfterSpacerVisible(spacerSize, containerSize);
|
_owner.OnAfterSpacerVisible(spacerSize, spacerSeparation, containerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
public async ValueTask DisposeAsync()
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.Components.Virtualization
|
||||||
Assert.NotNull(renderedVirtualize);
|
Assert.NotNull(renderedVirtualize);
|
||||||
|
|
||||||
// Simulate a JS spacer callback.
|
// Simulate a JS spacer callback.
|
||||||
((IVirtualizeJsCallbacks)renderedVirtualize).OnAfterSpacerVisible(10f, 100f);
|
((IVirtualizeJsCallbacks)renderedVirtualize).OnAfterSpacerVisible(10f, 50f, 100f);
|
||||||
|
|
||||||
// Validate that the exception is dispatched through the renderer.
|
// Validate that the exception is dispatched through the renderer.
|
||||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await testRenderer.RenderRootComponentAsync(componentId));
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await testRenderer.RenderRootComponentAsync(componentId));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import * as Msal from 'msal';
|
import * as Msal from '@azure/msal-browser';
|
||||||
import { StringDict } from 'msal/lib-commonjs/MsalTypes';
|
import { StringDict } from '@azure/msal-common';
|
||||||
import { ClientAuthErrorMessage } from 'msal/lib-commonjs/error/ClientAuthError';
|
|
||||||
|
|
||||||
interface AccessTokenRequestOptions {
|
interface AccessTokenRequestOptions {
|
||||||
scopes: string[];
|
scopes: string[];
|
||||||
|
|
@ -52,34 +51,53 @@ interface AuthorizeServiceConfiguration extends Msal.Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MsalAuthorizeService implements AuthorizeService {
|
class MsalAuthorizeService implements AuthorizeService {
|
||||||
readonly _msalApplication: Msal.UserAgentApplication;
|
private readonly _msalApplication: Msal.PublicClientApplication;
|
||||||
readonly _callbackPromise: Promise<AuthenticationResult>;
|
private _account: Msal.AccountInfo | undefined;
|
||||||
|
private _redirectCallback: Promise<AuthenticationResult | null> | undefined;
|
||||||
|
|
||||||
constructor(private readonly _settings: AuthorizeServiceConfiguration) {
|
constructor(private readonly _settings: AuthorizeServiceConfiguration) {
|
||||||
|
if (this._settings.auth?.knownAuthorities?.length == 0) {
|
||||||
|
this._settings.auth.knownAuthorities = [new URL(this._settings.auth.authority!).hostname]
|
||||||
|
}
|
||||||
|
this._msalApplication = new Msal.PublicClientApplication(this._settings);
|
||||||
|
}
|
||||||
|
|
||||||
// It is important that we capture the callback-url here as msal will remove the auth parameters
|
getAccount() {
|
||||||
// from the url as soon as it gets initialized.
|
if (this._account) {
|
||||||
const callbackUrl = location.href;
|
return this._account;
|
||||||
this._msalApplication = new Msal.UserAgentApplication(this._settings);
|
}
|
||||||
|
|
||||||
// This promise will only resolve in callback-paths, which is where we check it.
|
const accounts = this._msalApplication.getAllAccounts();
|
||||||
this._callbackPromise = this.createCallbackResult(callbackUrl);
|
if (accounts && accounts.length) {
|
||||||
|
return accounts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser() {
|
async getUser() {
|
||||||
const account = this._msalApplication.getAccount();
|
const account = this.getAccount();
|
||||||
return account?.idTokenClaims;
|
if (!account) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const silentRequest = {
|
||||||
|
redirectUri: this._settings.auth?.redirectUri,
|
||||||
|
account: account,
|
||||||
|
scopes: this._settings.defaultAccessTokenScopes
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||||
|
return response.idTokenClaims;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
|
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
|
||||||
try {
|
try {
|
||||||
const newToken = await this.getTokenCore(request?.scopes);
|
const newToken = await this.getTokenCore(request?.scopes);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: AccessTokenResultStatus.Success,
|
status: AccessTokenResultStatus.Success,
|
||||||
token: newToken
|
token: newToken
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: AccessTokenResultStatus.RequiresRedirect
|
status: AccessTokenResultStatus.RequiresRedirect
|
||||||
|
|
@ -88,12 +106,18 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTokenCore(scopes?: string[]): Promise<AccessToken | undefined> {
|
async getTokenCore(scopes?: string[]): Promise<AccessToken | undefined> {
|
||||||
const tokenScopes = {
|
const account = this.getAccount();
|
||||||
redirectUri: this._settings.auth.redirectUri as string,
|
if (!account) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const silentRequest = {
|
||||||
|
redirectUri: this._settings.auth?.redirectUri,
|
||||||
|
account: account,
|
||||||
scopes: scopes || this._settings.defaultAccessTokenScopes
|
scopes: scopes || this._settings.defaultAccessTokenScopes
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await this._msalApplication.acquireTokenSilent(tokenScopes);
|
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||||
return {
|
return {
|
||||||
value: response.accessToken,
|
value: response.accessToken,
|
||||||
grantedScopes: response.scopes,
|
grantedScopes: response.scopes,
|
||||||
|
|
@ -106,9 +130,10 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
// Before we start any sign-in flow, clear out any previous state so that it doesn't pile up.
|
// Before we start any sign-in flow, clear out any previous state so that it doesn't pile up.
|
||||||
this.purgeState();
|
this.purgeState();
|
||||||
|
|
||||||
const request: Msal.AuthenticationParameters = {
|
const request: Msal.AuthorizationUrlRequest = {
|
||||||
redirectUri: this._settings.auth.redirectUri as string,
|
redirectUri: this._settings.auth?.redirectUri,
|
||||||
state: await this.saveState(state)
|
state: await this.saveState(state),
|
||||||
|
scopes: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this._settings.defaultAccessTokenScopes && this._settings.defaultAccessTokenScopes.length > 0) {
|
if (this._settings.defaultAccessTokenScopes && this._settings.defaultAccessTokenScopes.length > 0) {
|
||||||
|
|
@ -130,7 +155,16 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
if (this._settings.defaultAccessTokenScopes?.length > 0) {
|
if (this._settings.defaultAccessTokenScopes?.length > 0) {
|
||||||
// This provisions the token as part of the sign-in flow eagerly so that is already in the cache
|
// This provisions the token as part of the sign-in flow eagerly so that is already in the cache
|
||||||
// when the app asks for it.
|
// when the app asks for it.
|
||||||
await this._msalApplication.acquireTokenSilent(request);
|
const account = this.getAccount();
|
||||||
|
if (!account) {
|
||||||
|
return this.error("No account to get tokens for.");
|
||||||
|
}
|
||||||
|
const silentRequest = {
|
||||||
|
redirectUri: request.redirectUri,
|
||||||
|
account: account,
|
||||||
|
scopes: request.scopes,
|
||||||
|
};
|
||||||
|
await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return this.error(e.errorMessage);
|
return this.error(e.errorMessage);
|
||||||
|
|
@ -142,33 +176,45 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async signInCore(request: Msal.AuthenticationParameters): Promise<Msal.AuthResponse | Msal.AuthError | undefined> {
|
async signInCore(request: Msal.AuthorizationUrlRequest): Promise<Msal.AuthenticationResult | Msal.AuthError | undefined> {
|
||||||
if (this._settings.loginMode.toLowerCase() === "redirect") {
|
const loginMode = this._settings.loginMode.toLowerCase();
|
||||||
try {
|
if (loginMode === 'redirect') {
|
||||||
this._msalApplication.loginRedirect(request);
|
return this.signInWithRedirect(request);
|
||||||
} catch (e) {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
return this.signInWithPopup(request);
|
||||||
return await this._msalApplication.loginPopup(request);
|
}
|
||||||
} catch (e) {
|
}
|
||||||
// If the user explicitly cancelled the pop-up, avoid performing a redirect.
|
|
||||||
if (this.isMsalError(e) && e.errorCode !== ClientAuthErrorMessage.userCancelledError.code) {
|
private async signInWithRedirect(request: Msal.RedirectRequest) {
|
||||||
try {
|
try {
|
||||||
this._msalApplication.loginRedirect(request);
|
return await this._msalApplication.loginRedirect(request);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return e;
|
|
||||||
}
|
private async signInWithPopup(request: Msal.PopupRequest) {
|
||||||
|
try {
|
||||||
|
return await this._msalApplication.loginPopup(request);
|
||||||
|
} catch (e) {
|
||||||
|
// If the user explicitly cancelled the pop-up, avoid performing a redirect.
|
||||||
|
if (this.isMsalError(e) && e.errorCode !== Msal.BrowserAuthErrorMessage.userCancelledError.code) {
|
||||||
|
this.signInWithRedirect(request);
|
||||||
|
} else {
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completeSignIn() {
|
async completeSignIn() {
|
||||||
return this._callbackPromise;
|
// Make sure that the redirect handler has completed execution before
|
||||||
|
// completing sign in.
|
||||||
|
await this._redirectCallback;
|
||||||
|
const account = this.getAccount();
|
||||||
|
if (account) {
|
||||||
|
return this.success(account);
|
||||||
|
}
|
||||||
|
return this.operationCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
async signOut(state: any) {
|
async signOut(state: any) {
|
||||||
|
|
@ -241,7 +287,7 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
// msal.js doesn't support the state parameter on logout flows, which forces us to shim our own logout state.
|
// msal.js doesn't support the state parameter on logout flows, which forces us to shim our own logout state.
|
||||||
// The format then is different, as msal follows the pattern state=<<guid>>|<<user_state>> and our format
|
// The format then is different, as msal follows the pattern state=<<guid>>|<<user_state>> and our format
|
||||||
// simple uses <<base64urlIdentifier>>.
|
// simple uses <<base64urlIdentifier>>.
|
||||||
const appState = !isLogout ? this._msalApplication.getAccountState(state[0]) : state[0];
|
const appState = !isLogout ? this.getAccountState(state[0]) : state[0];
|
||||||
const stateKey = `${AuthenticationService._infrastructureKey}.AuthorizeService.${appState}`;
|
const stateKey = `${AuthenticationService._infrastructureKey}.AuthorizeService.${appState}`;
|
||||||
const stateString = sessionStorage.getItem(stateKey);
|
const stateString = sessionStorage.getItem(stateKey);
|
||||||
if (stateString) {
|
if (stateString) {
|
||||||
|
|
@ -262,37 +308,35 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createCallbackResult(callbackUrl: string): Promise<AuthenticationResult> {
|
async initializeMsalHandler() {
|
||||||
// msal.js requires a callback to be registered during app initialization to handle redirect flows.
|
this._redirectCallback = this._msalApplication.handleRedirectPromise().then(
|
||||||
// To map that behavior to our API we register a callback early and store the result of that callback
|
(result: Msal.AuthenticationResult | null) => this.handleResult(result)
|
||||||
// as a promise on an instance field to be able to serve the state back to the main app.
|
).catch((error: any) => {
|
||||||
const promiseFactory = (resolve: (result: Msal.AuthResponse) => void, reject: (error: Msal.AuthError) => void): void => {
|
if (this.isMsalError(error)) {
|
||||||
this._msalApplication.handleRedirectCallback(
|
return this.error(error.errorMessage);
|
||||||
authenticationResponse => {
|
} else {
|
||||||
resolve(authenticationResponse);
|
return this.error(error);
|
||||||
},
|
}
|
||||||
authenticationError => {
|
})
|
||||||
reject(authenticationError);
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
private handleResult(result: Msal.AuthenticationResult | null) {
|
||||||
// Evaluate the promise to capture any authentication errors
|
if (result != null) {
|
||||||
await new Promise<Msal.AuthResponse>(promiseFactory);
|
this._account = result.account;
|
||||||
// See https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/FAQs#q6-how-to-avoid-page-reloads-when-acquiring-and-renewing-tokens-silently
|
return this.success(result.state);
|
||||||
if (window !== window.parent && !window.opener) {
|
} else {
|
||||||
return this.operationCompleted();
|
return this.operationCompleted();
|
||||||
} else {
|
}
|
||||||
const state = await this.retrieveState(callbackUrl);
|
}
|
||||||
return this.success(state);
|
|
||||||
}
|
private getAccountState(state: string) {
|
||||||
} catch (e) {
|
if (state) {
|
||||||
if (this.isMsalError(e)) {
|
const splitIndex = state.indexOf("|");
|
||||||
return this.error(e.errorMessage);
|
if (splitIndex > -1 && splitIndex + 1 < state.length) {
|
||||||
} else {
|
return state.substring(splitIndex + 1);
|
||||||
return this.error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isMsalError(resultOrError: any): resultOrError is Msal.AuthError {
|
private isMsalError(resultOrError: any): resultOrError is Msal.AuthError {
|
||||||
|
|
@ -319,14 +363,15 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
export class AuthenticationService {
|
export class AuthenticationService {
|
||||||
|
|
||||||
static _infrastructureKey = 'Microsoft.Authentication.WebAssembly.Msal';
|
static _infrastructureKey = 'Microsoft.Authentication.WebAssembly.Msal';
|
||||||
static _initialized = false;
|
static _initialized: Promise<void>;
|
||||||
static instance: MsalAuthorizeService;
|
static instance: MsalAuthorizeService;
|
||||||
|
|
||||||
public static async init(settings: AuthorizeServiceConfiguration) {
|
public static async init(settings: AuthorizeServiceConfiguration) {
|
||||||
if (!AuthenticationService._initialized) {
|
if (!AuthenticationService._initialized) {
|
||||||
AuthenticationService._initialized = true;
|
|
||||||
AuthenticationService.instance = new MsalAuthorizeService(settings);
|
AuthenticationService.instance = new MsalAuthorizeService(settings);
|
||||||
|
AuthenticationService._initialized = AuthenticationService.instance.initializeMsalHandler();
|
||||||
}
|
}
|
||||||
|
return AuthenticationService._initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getUser() {
|
public static getUser() {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,6 @@
|
||||||
"webpack-cli": "^3.3.10"
|
"webpack-cli": "^3.3.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"msal": "^1.2.1"
|
"@azure/msal-browser": "^2.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,20 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@azure/msal-browser@^2.0.0":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.0.0.tgz#09eb3ed2112bdcd11c751f1c0b9cec588b49b8c6"
|
||||||
|
integrity sha512-0L4XksaXmtl870bQTPxbHCkxMEMmSbsgkkVpb6bvXg8ngOLWnkxvV6tstj84JtQHcJPjNYkYY41jgBQxgC4/KQ==
|
||||||
|
dependencies:
|
||||||
|
"@azure/msal-common" "1.0.0"
|
||||||
|
|
||||||
|
"@azure/msal-common@1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-1.0.0.tgz#421f4859e6cb68cfacb03bb2c6c873efdffc76f0"
|
||||||
|
integrity sha512-l/+1Z9kQWLAlMwJ/c3MGhy4ujtEAK/3CMUaUXHvjUIsQknLFRb9+b3id5YSuToPfAvdUkAQGDZiQXosv1I+eLA==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.1"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.8.5":
|
"@webassemblyjs/ast@1.8.5":
|
||||||
version "1.8.5"
|
version "1.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
||||||
|
|
@ -690,6 +704,13 @@ debug@^2.2.0, debug@^2.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
debug@^4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||||
|
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.1"
|
||||||
|
|
||||||
decamelize@^1.2.0:
|
decamelize@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||||
|
|
@ -1667,12 +1688,10 @@ ms@2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||||
|
|
||||||
msal@^1.2.1:
|
ms@^2.1.1:
|
||||||
version "1.2.1"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/msal/-/msal-1.2.1.tgz#08133e37ab0b9741866c89a3fadc55aadb980723"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-Zo28eyRtT/Un+zcpMfPtTPD+eo/OqzsRER0k5dyk8Mje/K1oLlaEOAgZHlJs59Y2xyuVg8OrcKqSn/1MeNjZYw==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
dependencies:
|
|
||||||
tslib "^1.9.3"
|
|
||||||
|
|
||||||
nan@^2.12.1:
|
nan@^2.12.1:
|
||||||
version "2.14.0"
|
version "2.14.0"
|
||||||
|
|
@ -2485,7 +2504,7 @@ ts-loader@^6.2.1:
|
||||||
micromatch "^4.0.0"
|
micromatch "^4.0.0"
|
||||||
semver "^6.0.0"
|
semver "^6.0.0"
|
||||||
|
|
||||||
tslib@^1.9.0, tslib@^1.9.3:
|
tslib@^1.9.0:
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||||
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.Authentication.WebAssembly.Msal
|
namespace Microsoft.Authentication.WebAssembly.Msal
|
||||||
{
|
{
|
||||||
|
|
@ -48,5 +49,10 @@ namespace Microsoft.Authentication.WebAssembly.Msal
|
||||||
/// Gets or sets whether or not to navigate to the login request url after a successful login.
|
/// Gets or sets whether or not to navigate to the login request url after a successful login.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool NavigateToLoginRequestUrl { get; set; } = false;
|
public bool NavigateToLoginRequestUrl { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the set of known authority host names for the application.
|
||||||
|
/// </summary>
|
||||||
|
public IList<string> KnownAuthorities { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,17 +11,26 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
|
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
|
||||||
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This project compiles against Microsoft.AspNetCore.App from the SDK.
|
||||||
|
This ensures that it's packaging output is correct and does not include local artifacts.
|
||||||
|
-->
|
||||||
|
<UseAspNetCoreSharedRuntime>true</UseAspNetCoreSharedRuntime>
|
||||||
|
<DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>true</DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.AspNetCore" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
|
|
||||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
|
||||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
|
||||||
<Reference Include="Microsoft.AspNetCore.ResponseCompression" />
|
|
||||||
|
|
||||||
|
<ProjectReference
|
||||||
|
Include="$(RepoRoot)src\Framework\App.Runtime\src\Microsoft.AspNetCore.App.Runtime.csproj"
|
||||||
|
PrivateAssets="All"
|
||||||
|
ReferenceOutputAssembly="false"
|
||||||
|
SkipGetTargetFrameworkProperties="true" />
|
||||||
|
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.Hosting" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Pack settings -->
|
<!-- Pack settings -->
|
||||||
|
|
@ -36,19 +45,5 @@
|
||||||
<NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" />
|
<NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="_FixupRuntimeConfig" BeforeTargets="_GenerateRuntimeConfigurationFilesInputCache">
|
|
||||||
<ItemGroup>
|
|
||||||
<_RuntimeFramework Include="@(RuntimeFramework)" />
|
|
||||||
<RuntimeFramework Remove="@(RuntimeFramework)" />
|
|
||||||
<RuntimeFramework Include="Microsoft.AspNetCore.App" FrameworkName="Microsoft.AspNetCore.App" Version="5.0.0-preview" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="_UndoRuntimeConfigWorkarounds" AfterTargets="GenerateBuildRuntimeConfigurationFiles">
|
|
||||||
<ItemGroup>
|
|
||||||
<RuntimeFramework Remove="@(RuntimeFramework)" />
|
|
||||||
<RuntimeFramework Include="@(_RuntimeFramework)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,7 @@ namespace WebAssembly.JSInterop
|
||||||
// in driver.c in the Mono distribution
|
// in driver.c in the Mono distribution
|
||||||
/// See: https://github.com/mono/mono/blob/90574987940959fe386008a850982ea18236a533/sdks/wasm/src/driver.c#L318-L319
|
/// See: https://github.com/mono/mono/blob/90574987940959fe386008a850982ea18236a533/sdks/wasm/src/driver.c#L318-L319
|
||||||
|
|
||||||
// We're passing asyncHandle by ref not because we want it to be writable, but so it gets
|
|
||||||
// passed as a pointer (4 bytes). We can pass 4-byte values, but not 8-byte ones.
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
|
public static extern TRes InvokeJS<T0, T1, T2, TRes>(out string exception, ref JSCallInfo callInfo, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.Runtime.InteropServices;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace WebAssembly.JSInterop
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Explicit, Pack = 4)]
|
||||||
|
internal struct JSCallInfo
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public string FunctionIdentifier;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public JSCallResultType ResultType;
|
||||||
|
|
||||||
|
[FieldOffset(8)]
|
||||||
|
public string MarshalledCallArgsJson;
|
||||||
|
|
||||||
|
[FieldOffset(12)]
|
||||||
|
public long MarshalledCallAsyncHandle;
|
||||||
|
|
||||||
|
[FieldOffset(20)]
|
||||||
|
public long TargetInstanceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,22 +11,40 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
/// Provides methods for invoking JavaScript functions for applications running
|
/// Provides methods for invoking JavaScript functions for applications running
|
||||||
/// on the Mono WebAssembly runtime.
|
/// on the Mono WebAssembly runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class WebAssemblyJSRuntime : JSInProcessRuntime
|
public abstract class WebAssemblyJSRuntime : JSInProcessRuntime, IJSUnmarshalledRuntime
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override string InvokeJS(string identifier, string argsJson)
|
protected override string InvokeJS(string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||||
{
|
{
|
||||||
var noAsyncHandle = default(long);
|
var callInfo = new JSCallInfo
|
||||||
var result = InternalCalls.InvokeJSMarshalled(out var exception, ref noAsyncHandle, identifier, argsJson);
|
{
|
||||||
|
FunctionIdentifier = identifier,
|
||||||
|
TargetInstanceId = targetInstanceId,
|
||||||
|
ResultType = resultType,
|
||||||
|
MarshalledCallArgsJson = argsJson ?? "[]",
|
||||||
|
MarshalledCallAsyncHandle = default
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = InternalCalls.InvokeJS<object, object, object, string>(out var exception, ref callInfo, null, null, null);
|
||||||
|
|
||||||
return exception != null
|
return exception != null
|
||||||
? throw new JSException(exception)
|
? throw new JSException(exception)
|
||||||
: result;
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
|
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||||
{
|
{
|
||||||
InternalCalls.InvokeJSMarshalled(out _, ref asyncHandle, identifier, argsJson);
|
var callInfo = new JSCallInfo
|
||||||
|
{
|
||||||
|
FunctionIdentifier = identifier,
|
||||||
|
TargetInstanceId = targetInstanceId,
|
||||||
|
ResultType = resultType,
|
||||||
|
MarshalledCallArgsJson = argsJson ?? "[]",
|
||||||
|
MarshalledCallAsyncHandle = asyncHandle
|
||||||
|
};
|
||||||
|
|
||||||
|
InternalCalls.InvokeJS<object, object, object, string>(out _, ref callInfo, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
|
protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
|
||||||
|
|
@ -39,57 +57,32 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
// We pass 0 as the async handle because we don't want the JS-side code to
|
// We pass 0 as the async handle because we don't want the JS-side code to
|
||||||
// send back any notification (we're just providing a result for an existing async call)
|
// send back any notification (we're just providing a result for an existing async call)
|
||||||
var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions);
|
var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions);
|
||||||
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args, JSCallResultType.Default, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<TResult>(string identifier)
|
||||||
/// </summary>
|
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<TResult>(string identifier)
|
|
||||||
=> InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
||||||
/// </summary>
|
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
|
||||||
=> InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
||||||
/// </summary>
|
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <param name="arg1">The second argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
|
||||||
=> InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
|
||||||
/// <typeparam name="T2">The type of the third argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <param name="arg1">The second argument.</param>
|
|
||||||
/// <param name="arg2">The third argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
|
||||||
{
|
{
|
||||||
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
var callInfo = new JSCallInfo
|
||||||
|
{
|
||||||
|
FunctionIdentifier = identifier,
|
||||||
|
ResultType = ResultTypeFromGeneric<TResult>()
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = InternalCalls.InvokeJS<T0, T1, T2, TResult>(out var exception, ref callInfo, arg0, arg1, arg2);
|
||||||
|
|
||||||
return exception != null
|
return exception != null
|
||||||
? throw new JSException(exception)
|
? throw new JSException(exception)
|
||||||
: result;
|
: result;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
<Compile Include="..\src\BootJsonData.cs" LinkBase="Wasm" />
|
<Compile Include="..\src\BootJsonData.cs" LinkBase="Wasm" />
|
||||||
<Compile Include="..\src\AssetsManifestFile.cs" LinkBase="Wasm" />
|
<Compile Include="..\src\AssetsManifestFile.cs" LinkBase="Wasm" />
|
||||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||||
|
|
||||||
|
<EmbeddedResource Include="..\src\targets\BlazorWasm.web.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes">
|
<Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes">
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -88,6 +89,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||||
public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
|
public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||||
public async Task Publish_WithoutLinkerAndCompression_IsIncremental()
|
public async Task Publish_WithoutLinkerAndCompression_IsIncremental()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
|
|
||||||
// Verify web.config
|
// Verify web.config
|
||||||
Assert.FileExists(result, publishDirectory, "web.config");
|
Assert.FileExists(result, publishDirectory, "web.config");
|
||||||
|
var webConfigContent = new StreamReader(GetType().Assembly.GetManifestResourceStream("Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.BlazorWasm.web.config")).ReadToEnd();
|
||||||
|
Assert.FileContentEquals(result, Path.Combine(publishDirectory, "web.config"), webConfigContent);
|
||||||
Assert.FileCountEquals(result, 1, publishDirectory, "*", SearchOption.TopDirectoryOnly);
|
Assert.FileCountEquals(result, 1, publishDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
|
||||||
VerifyBootManifestHashes(result, blazorPublishDirectory);
|
VerifyBootManifestHashes(result, blazorPublishDirectory);
|
||||||
|
|
@ -141,11 +143,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
||||||
serviceWorkerContent: "// This is the production service worker",
|
serviceWorkerContent: "// This is the production service worker",
|
||||||
assetsManifestPath: "custom-service-worker-assets.js");
|
assetsManifestPath: "custom-service-worker-assets.js");
|
||||||
|
|
||||||
VerifyTypeGranularTrimming(result, blazorPublishDirectory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||||
public async Task Publish_InRelease_Works()
|
public async Task Publish_InRelease_Works()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -434,7 +435,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
Assert.Contains("System.Text.Json.dll", assemblies);
|
Assert.Contains("System.Text.Json.dll", assemblies);
|
||||||
|
|
||||||
// No pdbs
|
// No pdbs
|
||||||
Assert.Null(bootJsonData.resources.pdb);
|
// Testing this requires an update to the SDK in this repo. Re-enabling tracked via https://github.com/dotnet/aspnetcore/issues/25135
|
||||||
|
// Assert.Null(bootJsonData.resources.pdb);
|
||||||
Assert.Null(bootJsonData.resources.satelliteResources);
|
Assert.Null(bootJsonData.resources.satelliteResources);
|
||||||
|
|
||||||
Assert.Contains("appsettings.json", bootJsonData.config);
|
Assert.Contains("appsettings.json", bootJsonData.config);
|
||||||
|
|
@ -906,16 +908,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
|
|
||||||
private void VerifyTypeGranularTrimming(MSBuildResult result, string blazorPublishDirectory)
|
private void VerifyTypeGranularTrimming(MSBuildResult result, string blazorPublishDirectory)
|
||||||
{
|
{
|
||||||
var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");
|
var componentsShimAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.AspNetCore.Razor.Test.ComponentShim.dll");
|
||||||
Assert.FileExists(result, loggingAssemblyPath);
|
Assert.FileExists(result, componentsShimAssemblyPath);
|
||||||
|
|
||||||
// ILogger is referenced by the app, so we expect it to be preserved
|
// RouteView is referenced by the app, so we expect it to be preserved
|
||||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.ILogger");
|
Assert.AssemblyContainsType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.RouteView");
|
||||||
// LogLevel is referenced by ILogger and therefore must be preserved.
|
|
||||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.LogLevel");
|
|
||||||
|
|
||||||
// NullLogger is not referenced by the app, and should be trimmed.
|
// RouteData is referenced by RouteView so we expect it to be preserved.
|
||||||
Assert.AssemblyDoesNotContainType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.Abstractions.NullLogger");
|
Assert.AssemblyContainsType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.RouteData");
|
||||||
|
|
||||||
|
// CascadingParameterAttribute is not referenced by the app, and should be trimmed.
|
||||||
|
Assert.AssemblyDoesNotContainType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.CascadingParameterAttribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BootJsonData ReadBootJsonData(MSBuildResult result, string path)
|
private static BootJsonData ReadBootJsonData(MSBuildResult result, string path)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,18 @@ namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GenerateCommandLineCommands() => ToolAssembly;
|
private static string Quote(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path) || (path[0] == '\"' && path[path.Length - 1] == '\"'))
|
||||||
|
{
|
||||||
|
// it's already quoted
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"\"{path}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GenerateCommandLineCommands() => Quote(ToolAssembly);
|
||||||
|
|
||||||
protected override string GenerateResponseFileCommands()
|
protected override string GenerateResponseFileCommands()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||||
|
|
||||||
|
<!-- Turn off symbol publishing by default -->
|
||||||
|
<CopyOutputSymbolsToPublishDirectory>false</CopyOutputSymbolsToPublishDirectory>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Import Sdk="Microsoft.NET.Sdk.Razor" Project="Sdk.props" />
|
<Import Sdk="Microsoft.NET.Sdk.Razor" Project="Sdk.props" />
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,14 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
<!-- Trimmer defaults -->
|
<!-- Trimmer defaults -->
|
||||||
<PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
|
<PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
|
||||||
<TrimMode Condition="'$(TrimMode)' == ''">link</TrimMode>
|
<TrimMode Condition="'$(TrimMode)' == ''">link</TrimMode>
|
||||||
|
<TrimmerRemoveSymbols Condition="'$(TrimmerRemoveSymbols)' == ''">false</TrimmerRemoveSymbols>
|
||||||
|
|
||||||
|
<!-- Runtime feature defaults to trim unnecessary code -->
|
||||||
|
<EventSourceSupport Condition="'$(EventSourceSupport)' == ''">false</EventSourceSupport>
|
||||||
|
<UseSystemResourceKeys Condition="'$(UseSystemResourceKeys)' == ''">true</UseSystemResourceKeys>
|
||||||
|
<EnableUnsafeUTF7Encoding Condition="'$(EnableUnsafeUTF7Encoding)' == ''">false</EnableUnsafeUTF7Encoding>
|
||||||
|
<HttpActivityPropagationSupport Condition="'$(HttpActivityPropagationSupport)' == ''">false</HttpActivityPropagationSupport>
|
||||||
|
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
|
||||||
|
|
||||||
<StaticWebAssetBasePath Condition="'$(StaticWebAssetBasePath)' == ''">/</StaticWebAssetBasePath>
|
<StaticWebAssetBasePath Condition="'$(StaticWebAssetBasePath)' == ''">/</StaticWebAssetBasePath>
|
||||||
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
|
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
|
||||||
|
|
@ -69,6 +77,12 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Configuration for the platform compatibility analyzer. See https://github.com/dotnet/designs/blob/master/accepted/2020/platform-exclusion/platform-exclusion.md#build-configuration-for-platforms -->
|
||||||
|
<SupportedPlatform Remove="@(SupportedPlatform)" />
|
||||||
|
<SupportedPlatform Include="browser" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<Import Project="Microsoft.NET.Sdk.BlazorWebAssembly.ServiceWorkerAssetsManifest.targets" Condition="'$(ServiceWorkerAssetsManifest)' != ''" />
|
<Import Project="Microsoft.NET.Sdk.BlazorWebAssembly.ServiceWorkerAssetsManifest.targets" Condition="'$(ServiceWorkerAssetsManifest)' != ''" />
|
||||||
|
|
||||||
<Target Name="_ScrambleDotnetJsFileName" AfterTargets="ResolveRuntimePackAssets">
|
<Target Name="_ScrambleDotnetJsFileName" AfterTargets="ResolveRuntimePackAssets">
|
||||||
|
|
@ -395,7 +409,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<_BlazorTypeGranularAssembly
|
<_BlazorTypeGranularAssembly
|
||||||
Include="@(ManagedAssemblyToLink)"
|
Include="@(ManagedAssemblyToLink)"
|
||||||
Condition="'%(Extension)' == '.dll' AND ($([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.')) or $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.')))">
|
Condition="'%(Extension)' == '.dll' AND $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))">
|
||||||
<Required>false</Required>
|
<Required>false</Required>
|
||||||
<Preserve>all</Preserve>
|
<Preserve>all</Preserve>
|
||||||
</_BlazorTypeGranularAssembly>
|
</_BlazorTypeGranularAssembly>
|
||||||
|
|
@ -451,7 +465,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
Condition="'%(ResolvedFileToPublish.RelativePath)' != 'web.config' AND !$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
|
Condition="'%(ResolvedFileToPublish.RelativePath)' != 'web.config' AND !$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||||
|
|
||||||
<!-- Remove pdbs from the publish output -->
|
<!-- Remove pdbs from the publish output -->
|
||||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'$(BlazorWebAssemblyEnableDebugging)' != 'true' AND '%(Extension)' == '.pdb'" />
|
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'$(CopyOutputSymbolsToPublishDirectory)' != 'true' AND '%(Extension)' == '.pdb'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'@(ResolvedFileToPublish->AnyHaveMetadataValue('RelativePath', 'web.config'))' != 'true'">
|
<ItemGroup Condition="'@(ResolvedFileToPublish->AnyHaveMetadataValue('RelativePath', 'web.config'))' != 'true'">
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ namespace standalone
|
||||||
{
|
{
|
||||||
GC.KeepAlive(typeof(System.Text.Json.JsonSerializer));
|
GC.KeepAlive(typeof(System.Text.Json.JsonSerializer));
|
||||||
GC.KeepAlive(typeof(RazorClassLibrary.Class1));
|
GC.KeepAlive(typeof(RazorClassLibrary.Class1));
|
||||||
GC.KeepAlive(typeof(Microsoft.Extensions.Logging.ILogger));
|
|
||||||
#if REFERENCE_classlibrarywithsatelliteassemblies
|
#if REFERENCE_classlibrarywithsatelliteassemblies
|
||||||
GC.KeepAlive(typeof(classlibrarywithsatelliteassemblies.Class1));
|
GC.KeepAlive(typeof(classlibrarywithsatelliteassemblies.Class1));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
{
|
||||||
|
internal class RegisteredComponentsInterop
|
||||||
|
{
|
||||||
|
private static readonly string Prefix = "Blazor._internal.registeredComponents.";
|
||||||
|
|
||||||
|
public static readonly string GetRegisteredComponentsCount = Prefix + "getRegisteredComponentsCount";
|
||||||
|
|
||||||
|
public static readonly string GetId = Prefix + "getId";
|
||||||
|
|
||||||
|
public static readonly string GetAssembly = Prefix + "getAssembly";
|
||||||
|
|
||||||
|
public static readonly string GetTypeName = Prefix + "getTypeName";
|
||||||
|
|
||||||
|
public static readonly string GetParameterDefinitions = Prefix + "getParameterDefinitions";
|
||||||
|
|
||||||
|
public static readonly string GetParameterValues = Prefix + "getParameterValues";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// and <paramref name="selector"/>.
|
/// and <paramref name="selector"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||||
/// <param name="selector">The DOM element selector.</param>
|
/// <param name="selector">The DOM element selector or component registration id for the component.</param>
|
||||||
public RootComponentMapping(Type componentType, string selector)
|
public RootComponentMapping(Type componentType, string selector)
|
||||||
{
|
{
|
||||||
if (componentType is null)
|
if (componentType is null)
|
||||||
|
|
@ -38,6 +39,19 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
||||||
ComponentType = componentType;
|
ComponentType = componentType;
|
||||||
Selector = selector;
|
Selector = selector;
|
||||||
|
Parameters = ParameterView.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="RootComponentMapping"/> with the provided <paramref name="componentType"/>
|
||||||
|
/// and <paramref name="selector"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||||
|
/// <param name="selector">The DOM element selector or registration id for the component.</param>
|
||||||
|
/// <param name="parameters">The parameters to pass to the component.</param>
|
||||||
|
public RootComponentMapping(Type componentType, string selector, ParameterView parameters) : this(componentType, selector)
|
||||||
|
{
|
||||||
|
Parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -49,5 +63,10 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// Gets the DOM element selector.
|
/// Gets the DOM element selector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Selector { get; }
|
public string Selector { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the parameters to pass to the root component.
|
||||||
|
/// </summary>
|
||||||
|
public ParameterView Parameters { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,17 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||||
/// <param name="selector">The DOM element selector.</param>
|
/// <param name="selector">The DOM element selector.</param>
|
||||||
public void Add(Type componentType, string selector)
|
public void Add(Type componentType, string selector)
|
||||||
|
{
|
||||||
|
Add(componentType, selector, ParameterView.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a component mapping to the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||||
|
/// <param name="selector">The DOM element selector.</param>
|
||||||
|
/// <param name="parameters">The parameters to the root component.</param>
|
||||||
|
public void Add(Type componentType, string selector, ParameterView parameters)
|
||||||
{
|
{
|
||||||
if (componentType is null)
|
if (componentType is null)
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
throw new ArgumentNullException(nameof(selector));
|
throw new ArgumentNullException(nameof(selector));
|
||||||
}
|
}
|
||||||
|
|
||||||
Add(new RootComponentMapping(componentType, selector));
|
Add(new RootComponentMapping(componentType, selector, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
for (var i = 0; i < rootComponents.Length; i++)
|
for (var i = 0; i < rootComponents.Length; i++)
|
||||||
{
|
{
|
||||||
var rootComponent = rootComponents[i];
|
var rootComponent = rootComponents[i];
|
||||||
await _renderer.AddComponentAsync(rootComponent.ComponentType, rootComponent.Selector);
|
await _renderer.AddComponentAsync(rootComponent.ComponentType, rootComponent.Selector, rootComponent.Parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
await tcs.Task;
|
await tcs.Task;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public sealed class WebAssemblyHostBuilder
|
public sealed class WebAssemblyHostBuilder
|
||||||
{
|
{
|
||||||
private Func<IServiceProvider> _createServiceProvider;
|
private Func<IServiceProvider> _createServiceProvider;
|
||||||
|
private RootComponentTypeCache _rootComponentCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> using the most common
|
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> using the most common
|
||||||
|
|
@ -57,6 +58,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
||||||
// Retrieve required attributes from JSRuntimeInvoker
|
// Retrieve required attributes from JSRuntimeInvoker
|
||||||
InitializeNavigationManager(jsRuntimeInvoker);
|
InitializeNavigationManager(jsRuntimeInvoker);
|
||||||
|
InitializeRegisteredRootComponents(jsRuntimeInvoker);
|
||||||
InitializeDefaultServices();
|
InitializeDefaultServices();
|
||||||
|
|
||||||
var hostEnvironment = InitializeEnvironment(jsRuntimeInvoker);
|
var hostEnvironment = InitializeEnvironment(jsRuntimeInvoker);
|
||||||
|
|
@ -68,6 +70,38 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeRegisteredRootComponents(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||||
|
{
|
||||||
|
var componentsCount = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, int>(RegisteredComponentsInterop.GetRegisteredComponentsCount, null, null, null);
|
||||||
|
if (componentsCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var registeredComponents = new WebAssemblyComponentMarker[componentsCount];
|
||||||
|
for (var i = 0; i < componentsCount; i++)
|
||||||
|
{
|
||||||
|
var id = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, int>(RegisteredComponentsInterop.GetId, i, null, null);
|
||||||
|
var assembly = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetAssembly, id, null, null);
|
||||||
|
var typeName = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetTypeName, id, null, null);
|
||||||
|
var serializedParameterDefinitions = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetParameterDefinitions, id, null, null);
|
||||||
|
var serializedParameterValues = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetParameterValues, id, null, null);
|
||||||
|
registeredComponents[i] = new WebAssemblyComponentMarker(WebAssemblyComponentMarker.ClientMarkerType, assembly, typeName, serializedParameterDefinitions, serializedParameterValues, id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
var componentDeserializer = WebAssemblyComponentParameterDeserializer.Instance;
|
||||||
|
foreach (var registeredComponent in registeredComponents)
|
||||||
|
{
|
||||||
|
_rootComponentCache = new RootComponentTypeCache();
|
||||||
|
var componentType = _rootComponentCache.GetRootComponent(registeredComponent.Assembly, registeredComponent.TypeName);
|
||||||
|
var definitions = componentDeserializer.GetParameterDefinitions(registeredComponent.ParameterDefinitions);
|
||||||
|
var values = componentDeserializer.GetParameterValues(registeredComponent.ParameterValues);
|
||||||
|
var parameters = componentDeserializer.DeserializeParameters(definitions, values);
|
||||||
|
|
||||||
|
RootComponents.Add(componentType, registeredComponent.PrerenderId, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeNavigationManager(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
private void InitializeNavigationManager(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||||
{
|
{
|
||||||
var baseUri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetBaseUri, null, null, null);
|
var baseUri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetBaseUri, null, null, null);
|
||||||
|
|
@ -190,7 +224,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
Services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance);
|
Services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance);
|
||||||
Services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance);
|
Services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance);
|
||||||
Services.AddSingleton(new LazyAssemblyLoader(DefaultWebAssemblyJSRuntime.Instance));
|
Services.AddSingleton(new LazyAssemblyLoader(DefaultWebAssemblyJSRuntime.Instance));
|
||||||
Services.AddLogging(builder => {
|
Services.AddLogging(builder =>
|
||||||
|
{
|
||||||
builder.AddProvider(new WebAssemblyConsoleLoggerProvider(DefaultWebAssemblyJSRuntime.Instance));
|
builder.AddProvider(new WebAssemblyConsoleLoggerProvider(DefaultWebAssemblyJSRuntime.Instance));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||||
|
|
@ -15,13 +15,7 @@
|
||||||
<Reference Include="Microsoft.Extensions.Logging" />
|
<Reference Include="Microsoft.Extensions.Logging" />
|
||||||
<Reference Include="Microsoft.JSInterop.WebAssembly" />
|
<Reference Include="Microsoft.JSInterop.WebAssembly" />
|
||||||
|
|
||||||
<ProjectReference
|
<ProjectReference Include="..\..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" ReferenceOutputAssemblies="false" SkipGetTargetFrameworkProperties="true" UndefineProperties="TargetFramework" Private="false" Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
||||||
Include="..\..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
|
||||||
ReferenceOutputAssemblies="false"
|
|
||||||
SkipGetTargetFrameworkProperties="true"
|
|
||||||
UndefineProperties="TargetFramework"
|
|
||||||
Private="false"
|
|
||||||
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
|
||||||
|
|
||||||
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" />
|
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
@ -31,6 +25,11 @@
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\JsonSerializerOptionsProvider.cs" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\JsonSerializerOptionsProvider.cs" />
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\WebEventData.cs" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\WebEventData.cs" />
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
||||||
|
<Compile Include="$(ComponentsSharedSourceRoot)src\ComponentParametersTypeCache.cs" />
|
||||||
|
<Compile Include="$(ComponentsSharedSourceRoot)src\RootComponentTypeCache.cs" />
|
||||||
|
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentSerializationSettings.cs" Link="Prerendering/WebAssemblyComponentSerializationSettings.cs" />
|
||||||
|
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentMarker.cs" Link="Prerendering/WebAssemblyComponentMarker.cs" />
|
||||||
|
<Compile Include="$(SharedSourceRoot)Components\ComponentParameter.cs" Link="Prerendering/ComponentParameter.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components
|
||||||
|
{
|
||||||
|
internal class WebAssemblyComponentParameterDeserializer
|
||||||
|
{
|
||||||
|
private readonly ComponentParametersTypeCache _parametersCache;
|
||||||
|
|
||||||
|
public WebAssemblyComponentParameterDeserializer(
|
||||||
|
ComponentParametersTypeCache parametersCache)
|
||||||
|
{
|
||||||
|
_parametersCache = parametersCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebAssemblyComponentParameterDeserializer Instance { get; } = new WebAssemblyComponentParameterDeserializer(new ComponentParametersTypeCache());
|
||||||
|
|
||||||
|
public ParameterView DeserializeParameters(IList<ComponentParameter> parametersDefinitions, IList<object> parameterValues)
|
||||||
|
{
|
||||||
|
var parametersDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (parameterValues.Count != parametersDefinitions.Count)
|
||||||
|
{
|
||||||
|
// Mismatched number of definition/parameter values.
|
||||||
|
throw new InvalidOperationException($"The number of parameter definitions '{parametersDefinitions.Count}' does not match the number parameter values '{parameterValues.Count}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < parametersDefinitions.Count; i++)
|
||||||
|
{
|
||||||
|
var definition = parametersDefinitions[i];
|
||||||
|
if (definition.Name == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The name is missing in a parameter definition.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.TypeName == null && definition.Assembly == null)
|
||||||
|
{
|
||||||
|
parametersDictionary[definition.Name] = null;
|
||||||
|
}
|
||||||
|
else if (definition.TypeName == null || definition.Assembly == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"The parameter definition for '{definition.Name}' is incomplete: Type='{definition.TypeName}' Assembly='{definition.Assembly}'.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var parameterType = _parametersCache.GetParameterType(definition.Assembly, definition.TypeName);
|
||||||
|
if (parameterType == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"The parameter '{definition.Name} with type '{definition.TypeName}' in assembly '{definition.Assembly}' could not be found.");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var value = (JsonElement)parameterValues[i];
|
||||||
|
var parameterValue = JsonSerializer.Deserialize(
|
||||||
|
value.GetRawText(),
|
||||||
|
parameterType,
|
||||||
|
WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||||
|
|
||||||
|
parametersDictionary[definition.Name] = parameterValue;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Could not parse the parameter value for parameter '{definition.Name}' of type '{definition.TypeName}' and assembly '{definition.Assembly}'.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParameterView.FromDictionary(parametersDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComponentParameter[] GetParameterDefinitions(string parametersDefinitions)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<ComponentParameter[]>(parametersDefinitions, WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<object> GetParameterValues(string parameterValues)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<IList<object>>(parameterValues, WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components.RenderTree;
|
using Microsoft.AspNetCore.Components.RenderTree;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
using Microsoft.JSInterop.WebAssembly;
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
|
|
@ -46,13 +47,14 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TComponent">The type of the component.</typeparam>
|
/// <typeparam name="TComponent">The type of the component.</typeparam>
|
||||||
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
||||||
|
/// <param name="parameters">The parameters for the component.</param>
|
||||||
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
||||||
/// want to await the rendering of the added component.
|
/// want to await the rendering of the added component.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Task AddComponentAsync<TComponent>(string domElementSelector) where TComponent : IComponent
|
public Task AddComponentAsync<TComponent>(string domElementSelector, ParameterView parameters) where TComponent : IComponent
|
||||||
=> AddComponentAsync(typeof(TComponent), domElementSelector);
|
=> AddComponentAsync(typeof(TComponent), domElementSelector, parameters);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Associates the <see cref="IComponent"/> with the <see cref="WebAssemblyRenderer"/>,
|
/// Associates the <see cref="IComponent"/> with the <see cref="WebAssemblyRenderer"/>,
|
||||||
|
|
@ -60,12 +62,13 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="componentType">The type of the component.</param>
|
/// <param name="componentType">The type of the component.</param>
|
||||||
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
||||||
|
/// <param name="parameters">The list of root component parameters.</param>
|
||||||
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
||||||
/// want to await the rendering of the added component.
|
/// want to await the rendering of the added component.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Task AddComponentAsync(Type componentType, string domElementSelector)
|
public Task AddComponentAsync(Type componentType, string domElementSelector, ParameterView parameters)
|
||||||
{
|
{
|
||||||
var component = InstantiateComponent(componentType);
|
var component = InstantiateComponent(componentType);
|
||||||
var componentId = AssignRootComponentId(component);
|
var componentId = AssignRootComponentId(component);
|
||||||
|
|
@ -82,7 +85,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
componentId,
|
componentId,
|
||||||
_webAssemblyRendererId);
|
_webAssemblyRendererId);
|
||||||
|
|
||||||
return RenderRootComponentAsync(componentId);
|
return RenderRootComponentAsync(componentId, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -95,7 +98,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Task UpdateDisplayAsync(in RenderBatch batch)
|
protected override Task UpdateDisplayAsync(in RenderBatch batch)
|
||||||
{
|
{
|
||||||
DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<int, RenderBatch, object>(
|
((IJSUnmarshalledRuntime)DefaultWebAssemblyJSRuntime.Instance).InvokeUnmarshalled<int, RenderBatch, object>(
|
||||||
"Blazor._internal.renderBatch",
|
"Blazor._internal.renderBatch",
|
||||||
_webAssemblyRendererId,
|
_webAssemblyRendererId,
|
||||||
batch);
|
batch);
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
var newAssembliesToLoad = assembliesToLoad.Where(assembly => !_loadedAssemblyCache.Contains(assembly));
|
var newAssembliesToLoad = assembliesToLoad.Where(assembly => !_loadedAssemblyCache.Contains(assembly));
|
||||||
var loadedAssemblies = new List<Assembly>();
|
var loadedAssemblies = new List<Assembly>();
|
||||||
|
|
||||||
var count = (int)await ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled<string[], object, object, Task<object>>(
|
var count = (int)await ((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<string[], object, object, Task<object>>(
|
||||||
GetDynamicAssemblies,
|
GetDynamicAssemblies,
|
||||||
newAssembliesToLoad.ToArray(),
|
newAssembliesToLoad.ToArray(),
|
||||||
null,
|
null,
|
||||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
return loadedAssemblies;
|
return loadedAssemblies;
|
||||||
}
|
}
|
||||||
|
|
||||||
var assemblies = ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled<object, object, object, object[]>(
|
var assemblies = ((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<object, object, object, object[]>(
|
||||||
ReadDynamicAssemblies,
|
ReadDynamicAssemblies,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
_jsRuntime.InvokeVoid("console.error", formattedMessage);
|
_jsRuntime.InvokeVoid("console.error", formattedMessage);
|
||||||
break;
|
break;
|
||||||
case LogLevel.Critical:
|
case LogLevel.Critical:
|
||||||
_jsRuntime.InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
|
((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
|
||||||
break;
|
break;
|
||||||
default: // LogLevel.None or invalid enum values
|
default: // LogLevel.None or invalid enum values
|
||||||
Console.WriteLine(formattedMessage);
|
Console.WriteLine(formattedMessage);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.JSInterop.WebAssembly;
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class exists to enable unit testing for code that needs to call
|
/// This class exists to enable unit testing for code that needs to call
|
||||||
/// <see cref="WebAssemblyJSRuntime.InvokeUnmarshalled{T0, T1, T2, TResult}(string, T0, T1, T2)"/>.
|
/// <see cref="IJSUnmarshalledRuntime.InvokeUnmarshalled{T0, T1, T2, TResult}(string, T0, T1, T2)"/>.
|
||||||
///
|
///
|
||||||
/// We should only use this in non-perf-critical code paths (for example, during hosting startup,
|
/// We should only use this in non-perf-critical code paths (for example, during hosting startup,
|
||||||
/// where we only call this a fixed number of times, and not during rendering where it might be
|
/// where we only call this a fixed number of times, and not during rendering where it might be
|
||||||
|
|
@ -22,6 +22,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
public static WebAssemblyJSRuntimeInvoker Instance = new WebAssemblyJSRuntimeInvoker();
|
public static WebAssemblyJSRuntimeInvoker Instance = new WebAssemblyJSRuntimeInvoker();
|
||||||
|
|
||||||
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||||
=> DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2);
|
=> ((IJSUnmarshalledRuntime)DefaultWebAssemblyJSRuntime.Instance).InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue