Merge branch 'master' into merge/release/5.0-preview7-to-master

This commit is contained in:
Pranav K 2020-07-05 20:54:56 -07:00 committed by GitHub
commit de034feb98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
373 changed files with 5277 additions and 1913 deletions

View File

@ -433,7 +433,8 @@ stages:
jobName: Linux_musl_x64_build jobName: Linux_musl_x64_build
jobDisplayName: "Build: Linux Musl x64" jobDisplayName: "Build: Linux Musl x64"
agentOs: Linux agentOs: Linux
buildScript: ./dockerbuild.sh alpine container: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.9-WithNode-0fc54a3-20190918214015
buildScript: ./build.sh
buildArgs: buildArgs:
--arch x64 --arch x64
--os-name linux-musl --os-name linux-musl
@ -448,6 +449,7 @@ stages:
$(_InternalRuntimeDownloadArgs) $(_InternalRuntimeDownloadArgs)
installNodeJs: false installNodeJs: false
installJdk: false installJdk: false
skipComponentGovernanceDetection: true
artifacts: artifacts:
- name: Linux_musl_x64_Logs - name: Linux_musl_x64_Logs
path: artifacts/log/ path: artifacts/log/
@ -466,7 +468,8 @@ stages:
jobDisplayName: "Build: Linux Musl ARM64" jobDisplayName: "Build: Linux Musl ARM64"
agentOs: Linux agentOs: Linux
useHostedUbuntu: false useHostedUbuntu: false
buildScript: ./dockerbuild.sh ubuntu-alpine37 container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine-20200413125008-406629a
buildScript: ./build.sh
buildArgs: buildArgs:
--arch arm64 --arch arm64
--os-name linux-musl --os-name linux-musl

View File

@ -35,7 +35,8 @@
# Specifies what directory to run build.sh/cmd # Specifies what directory to run build.sh/cmd
# buildScript: string # buildScript: string
# Specifies the build script to run. Defaults to build.sh or build.cmd. # Specifies the build script to run. Defaults to build.sh or build.cmd.
# skipComponentGovernanceDetection: boolean
# Determines if component governance detection can be skipped
# #
# See https://docs.microsoft.com/en-us/vsts/pipelines/yaml-schema for details # See https://docs.microsoft.com/en-us/vsts/pipelines/yaml-schema for details
# #
@ -60,6 +61,7 @@ parameters:
installJdk: true installJdk: true
timeoutInMinutes: 180 timeoutInMinutes: 180
useHostedUbuntu: true useHostedUbuntu: true
skipComponentGovernanceDetection: false
# We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case). # We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case).
# This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build # This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build
@ -114,6 +116,8 @@ jobs:
name: NetCoreInternal-Pool name: NetCoreInternal-Pool
# Visual Studio Enterprise - contains some stuff, like SQL Server and IIS Express, that we use for testing # Visual Studio Enterprise - contains some stuff, like SQL Server and IIS Express, that we use for testing
queue: BuildPool.Server.Amd64.VS2019 queue: BuildPool.Server.Amd64.VS2019
${{ if ne(parameters.container, '') }}:
container: ${{ parameters.container }}
variables: variables:
- AgentOsName: ${{ parameters.agentOs }} - AgentOsName: ${{ parameters.agentOs }}
- ASPNETCORE_TEST_LOG_MAXPATH: "200" # Keep test log file name length low enough for artifact zipping - ASPNETCORE_TEST_LOG_MAXPATH: "200" # Keep test log file name length low enough for artifact zipping
@ -238,7 +242,7 @@ jobs:
continueOnError: true continueOnError: true
condition: always() condition: always()
- ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), ne(parameters.skipComponentGovernanceDetection, 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
condition: and(succeeded(), ne(variables['CG_RAN'], 'true')) condition: and(succeeded(), ne(variables['CG_RAN'], 'true'))
displayName: 'Component Detection' displayName: 'Component Detection'

View File

@ -0,0 +1,149 @@
# We want to run quarantined tests on master as well as on PRs
trigger:
batch: true
branches:
include:
- master
schedules:
- cron: "0 */4 * * *"
displayName: Every 4 hours test run
branches:
include:
- master
always: true
variables:
- ${{ if ne(variables['System.TeamProject'], 'internal') }}:
- name: _UseHelixOpenQueues
value: 'true'
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- group: DotNet-HelixApi-Access
- name: _UseHelixOpenQueues
value: 'false'
jobs:
- template: jobs/default-build.yml
parameters:
jobName: Helix_quarantined_x64
jobDisplayName: 'Tests: Helix'
agentOs: Windows
timeoutInMinutes: 240
steps:
# Build the shared framework
- script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Build shared fx
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj
displayName: Restore interop projects
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative
-projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true
/p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Run build.cmd helix target
continueOnError: true
env:
HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues
SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops
artifacts:
- name: Helix_logs
path: artifacts/log/
publishOnError: true
- template: jobs/default-build.yml
parameters:
jobName: Windows_Quarantined_x64
jobDisplayName: 'Tests: Windows x64'
agentOs: Windows
timeoutInMinutes: 240
isTestingJob: true
steps:
- powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava"
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true"
displayName: Pack Templates
- script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true"
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Windows_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Windows_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: MacOS_Quarantined_Test
jobDisplayName: "Tests: macOS 10.14"
agentOs: macOS
timeoutInMinutes: 240
isTestingJob: true
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: MacOS_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: MacOS_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: Linux_Quarantined_Test
jobDisplayName: "Tests: Ubuntu 16.04 x64"
agentOs: Linux
timeoutInMinutes: 240
isTestingJob: true
useHostedUbuntu: false
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Linux_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Linux_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true

View File

@ -1,13 +1,10 @@
# We want to run quarantined tests on master as well as on PRs # We only want to run quarantined tests on master
trigger: pr: none
batch: true trigger: none
branches:
include:
- master
schedules: schedules:
- cron: "0 */4 * * *" - cron: "0 18 * * *"
displayName: Every 4 hours test run displayName: Run tests once a day at 11 PM
branches: branches:
include: include:
- master - master
@ -28,7 +25,7 @@ jobs:
jobName: Helix_quarantined_x64 jobName: Helix_quarantined_x64
jobDisplayName: 'Tests: Helix' jobDisplayName: 'Tests: Helix'
agentOs: Windows agentOs: Windows
timeoutInMinutes: 180 timeoutInMinutes: 480
steps: steps:
# Build the shared framework # Build the shared framework
- script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log - script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
@ -36,7 +33,7 @@ jobs:
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj - script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj
displayName: Restore interop projects displayName: Restore interop projects
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative - script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative
-projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true -projects eng\helix\helix.proj /p:IsHelixDaily=true /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true
/p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log /p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Run build.cmd helix target displayName: Run build.cmd helix target
continueOnError: true continueOnError: true
@ -48,102 +45,27 @@ jobs:
path: artifacts/log/ path: artifacts/log/
publishOnError: true publishOnError: true
# Helix ARM64
- template: jobs/default-build.yml - template: jobs/default-build.yml
parameters: parameters:
jobName: Windows_Quarantined_x64 jobName: Helix_quarantined_arm64
jobDisplayName: 'Tests: Windows x64' jobDisplayName: "Tests: Helix ARM64"
agentOs: Windows
timeoutInMinutes: 180
isTestingJob: true
steps:
- powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava"
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true"
displayName: Pack Templates
- script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true"
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Windows_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Windows_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: MacOS_Quarantined_Test
jobDisplayName: "Tests: macOS 10.14"
agentOs: macOS
timeoutInMinutes: 180
isTestingJob: true
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: MacOS_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: MacOS_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: Linux_Quarantined_Test
jobDisplayName: "Tests: Ubuntu 16.04 x64"
agentOs: Linux agentOs: Linux
timeoutInMinutes: 180 timeoutInMinutes: 480
isTestingJob: true
useHostedUbuntu: false
steps: steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java - script: ./restore.sh -ci -nobl
displayName: Build displayName: Restore
# The templates part can be removed when the Blazor Templates run on Helix - script: ./build.sh --ci --nobl --noBuildRepoTasks --arch arm64 -test --no-build-nodejs --all --projects
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps $(Build.SourcesDirectory)/eng/helix/helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:RunQuarantinedTests=true
displayName: Pack Templates (for Template tests) /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true displayName: Run build.sh helix arm64 target
displayName: Run Quarantined Tests
continueOnError: true continueOnError: true
- task: PublishTestResults@2 env:
displayName: Publish Quarantined Test Results HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues
inputs: SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops
testResultsFormat: 'xUnit' installNodeJs: false
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts: artifacts:
- name: Linux_Quarantined_Test_Logs - name: Helix_arm64_logs
path: artifacts/log/ path: artifacts/log/
publishOnError: true publishOnError: true
includeForks: true includeForks: true
- name: Linux_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true

6
.github/CODEOWNERS vendored
View File

@ -9,14 +9,16 @@
/eng/common/ @dotnet-maestro-bot /eng/common/ @dotnet-maestro-bot
/eng/Versions.props @dotnet-maestro-bot @dougbu /eng/Versions.props @dotnet-maestro-bot @dougbu
/eng/Version.Details.xml @dotnet-maestro-bot @dougbu /eng/Version.Details.xml @dotnet-maestro-bot @dougbu
/src/Components/ @SteveSandersonMS /src/Components/ @SteveSandersonMS @aspnet-blazor-eng
/src/DefaultBuilder/ @tratcher /src/DefaultBuilder/ @tratcher
/src/Hosting/ @tratcher /src/Hosting/ @tratcher
/src/Http/ @tratcher @jkotalik /src/Http/ @tratcher @jkotalik
/src/Middleware/ @tratcher /src/Middleware/ @tratcher
/src/Middleware/HttpsPolicy/ @jkotalik /src/Middleware/HttpsPolicy/ @jkotalik
/src/Middleware/Rewrite/ @jkotalik /src/Middleware/Rewrite/ @jkotalik
# /src/ProjectTemplates/ @ryanbrandenburg # /src/ProjectTemplates/ @ryanbrandenburg
/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/ @aspnet-blazor-eng
/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/ @aspnet-blazor-eng
/src/Security/ @tratcher /src/Security/ @tratcher
/src/Servers/ @tratcher @jkotalik @halter73 /src/Servers/ @tratcher @jkotalik @halter73
/src/Shared/runtime/ @dotnet/http /src/Shared/runtime/ @dotnet/http

View File

@ -68,6 +68,8 @@ To update an existing copy, run:
git submodule update --init --recursive git submodule update --init --recursive
``` ```
**NOTE** some ISPs have been know to use web filtering software that has caused issues with git repository cloning, if you experience issues cloning this repo please review <https://help.github.com/en/github/authenticating-to-github/using-ssh-over-the-https-port>
## Building in Visual Studio ## Building in Visual Studio
Before opening our .sln files in Visual Studio or VS Code, you need to perform the following actions. Before opening our .sln files in Visual Studio or VS Code, you need to perform the following actions.
@ -228,6 +230,16 @@ TargetOsName | The base runtime identifier to build for (win, linux,
After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core. After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core.
See ["Artifacts"](./Artifacts.md) for more explanation of the different folders produced by a build. See ["Artifacts"](./Artifacts.md) for more explanation of the different folders produced by a build.
Building installers does not run as part of `build.cmd` run without parameters, so you should opt-in for building them:
```ps1
.\build.cmd -all -pack -arch x64
.\build.cmd -all -pack -arch x86 -noBuildJava
.\build.cmd -buildInstallers
```
*Note*: Additional build steps listed above aren't necessary on Linux or macOS.
* Run the installers produced in `artifacts/installers/{Debug, Release}/` for your platform. * Run the installers produced in `artifacts/installers/{Debug, Release}/` for your platform.
* Add a NuGet.Config to your project directory with the following content: * Add a NuGet.Config to your project directory with the following content:

View File

@ -20,12 +20,23 @@ This will restore, and then publish all the test project including some bootstra
- Required queues: Windows10, OSX, Ubuntu1604 - Required queues: Windows10, OSX, Ubuntu1604
- Full queue matrix: Windows[7, 81, 10], Ubuntu[1604, 1804, 2004], Centos7, Debian[8,9], Redhat7, Fedora28, Arm64 (Win10, Debian9) - Full queue matrix: Windows[7, 81, 10], Ubuntu[1604, 1804, 2004], Centos7, Debian[8,9], Redhat7, Fedora28, Arm64 (Win10, Debian9)
- The queues are defined in [Helix.Common.props](https://github.com/dotnet/aspnetcore/blob/master/eng/targets/Helix.Common.props)
aspnetcore-ci runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches. [aspnetcore-ci](https://dev.azure.com/dnceng/public/_build?definitionId=278) runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches.
aspnetcore-quarantined-tests runs only quarantined tests against the required queues only on master every 4 hours. [aspnetcore-helix-matrix](https://dev.azure.com/dnceng/public/_build?definitionId=837) runs non quarantined tests against all queues twice a day only on public master.
[aspnetcore-quarantined-pr](https://dev.azure.com/dnceng/public/_build?definitionId=869) runs only quarantined tests against the required queues on PRs and on master every 4 hours.
[aspnetcore-quarantined-tests](https://dev.azure.com/dnceng/public/_build?definitionId=331) runs only quarantined tests against all queues only on public master once a day at 11 PM.
You can always manually queue pipeline runs by clicking on the link to the pipeline -> Run Pipeline -> select your branch/tag and commit
## Checkin process expectations
- The normal PR process has aspnetcore-ci will ensure that the required queues are green.
- If your changes are likely to have cross platform impact that would affect more than the required queues, you should kick off a manual aspnetcore-helix-matrix pipeline run against your branch before merging your PR. Even though aspnetcore-helix-matrix is not a required checkin gate, if your changes break this pipeline, you must either immediately revert your changes, or quarantine the test, its never ok to leave this pipeline in a broken state.
aspnetcore-helix-matrix runs non quarantined tests against all queues twice a day only on public master.
## How do I look at the results of a helix run on Azure Pipelines? ## How do I look at the results of a helix run on Azure Pipelines?

View File

@ -3,3 +3,9 @@ Contributor documentation
The primary audience for documentation in this folder is contributors to ASP.NET Core. The primary audience for documentation in this folder is contributors to ASP.NET Core.
If you are looking for documentation on how to *use* ASP.NET Core, go to <https://docs.asp.net>. If you are looking for documentation on how to *use* ASP.NET Core, go to <https://docs.asp.net>.
# ASP.NET Core developer workflow
- [Building from source](BuildFromSource.md)
- [Troubleshooting build errors](BuildErrors.md)
- [Artifacts structure](Artifacts.md)

View File

@ -67,7 +67,6 @@
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" /> <ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" /> <ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" /> <ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
<ProjectReferenceProvider Include="System.Net.Http.WebAssemblyHttpHandler" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" /> <ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Testing" ProjectPath="$(RepoRoot)src\Testing\src\Microsoft.AspNetCore.Testing.csproj" /> <ProjectReferenceProvider Include="Microsoft.AspNetCore.Testing" ProjectPath="$(RepoRoot)src\Testing\src\Microsoft.AspNetCore.Testing.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" RefProjectPath="$(RepoRoot)src\DefaultBuilder\ref\Microsoft.AspNetCore.csproj" /> <ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" RefProjectPath="$(RepoRoot)src\DefaultBuilder\ref\Microsoft.AspNetCore.csproj" />

View File

@ -13,288 +13,288 @@
<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-preview.7.20326.1"> <Dependency Name="dotnet-ef" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha> <Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Drawing.Common" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Drawing.Common" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.IO.Pipelines" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.IO.Pipelines" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Net.Http.Json" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Net.Http.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Reflection.Metadata" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Security.Permissions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Security.Permissions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Security.Principal.Windows" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Text.Encodings.Web" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Text.Json" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Text.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Threading.Channels" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Threading.Channels" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="System.Windows.Extensions" Version="5.0.0-preview.7.20326.1"> <Dependency Name="System.Windows.Extensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</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-preview.7.20326.1"> <Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-preview.7.20326.1"> <Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</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-preview.7.20326.1"> <Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha> <Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20316.1"> <Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20316.1">
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>

View File

@ -9,7 +9,7 @@
<AspNetCoreMajorVersion>5</AspNetCoreMajorVersion> <AspNetCoreMajorVersion>5</AspNetCoreMajorVersion>
<AspNetCoreMinorVersion>0</AspNetCoreMinorVersion> <AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
<AspNetCorePatchVersion>0</AspNetCorePatchVersion> <AspNetCorePatchVersion>0</AspNetCorePatchVersion>
<PreReleaseVersionIteration>7</PreReleaseVersionIteration> <PreReleaseVersionIteration>8</PreReleaseVersionIteration>
<!-- <!--
When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages
--> -->
@ -66,79 +66,79 @@
<!-- Packages from dotnet/roslyn --> <!-- Packages from dotnet/roslyn -->
<MicrosoftNetCompilersToolsetPackageVersion>3.7.0-4.20319.6</MicrosoftNetCompilersToolsetPackageVersion> <MicrosoftNetCompilersToolsetPackageVersion>3.7.0-4.20319.6</MicrosoftNetCompilersToolsetPackageVersion>
<!-- Packages from dotnet/runtime --> <!-- Packages from dotnet/runtime -->
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyModelPackageVersion> <MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppInternalPackageVersion> <MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppInternalPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppRefPackageVersion> <MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppRuntimewinx64PackageVersion> <MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
<MicrosoftWin32RegistryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftWin32RegistryPackageVersion> <MicrosoftWin32RegistryPackageVersion>5.0.0-preview.8.20352.6</MicrosoftWin32RegistryPackageVersion>
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftWin32SystemEventsPackageVersion> <MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftWin32SystemEventsPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsCachingAbstractionsPackageVersion> <MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsCachingMemoryPackageVersion> <MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationAbstractionsPackageVersion> <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationBinderPackageVersion> <MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion> <MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion> <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion> <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationIniPackageVersion> <MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationJsonPackageVersion> <MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationPackageVersion> <MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion> <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationXmlPackageVersion> <MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion> <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyInjectionPackageVersion> <MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion> <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersCompositePackageVersion> <MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersPhysicalPackageVersion> <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileSystemGlobbingPackageVersion> <MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion> <MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostingAbstractionsPackageVersion> <MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostingPackageVersion> <MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHttpPackageVersion> <MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion> <MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingConfigurationPackageVersion> <MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingConsolePackageVersion> <MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingDebugPackageVersion> <MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingEventSourcePackageVersion> <MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingEventLogPackageVersion> <MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingPackageVersion> <MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingTraceSourcePackageVersion> <MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion> <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion> <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsPrimitivesPackageVersion> <MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsInternalTransportPackageVersion> <MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsInternalTransportPackageVersion>
<SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.7.20326.1</SystemComponentModelAnnotationsPackageVersion> <SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.8.20352.6</SystemComponentModelAnnotationsPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.7.20326.1</SystemDiagnosticsDiagnosticSourcePackageVersion> <SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.8.20352.6</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.7.20326.1</SystemDiagnosticsEventLogPackageVersion> <SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.8.20352.6</SystemDiagnosticsEventLogPackageVersion>
<SystemDrawingCommonPackageVersion>5.0.0-preview.7.20326.1</SystemDrawingCommonPackageVersion> <SystemDrawingCommonPackageVersion>5.0.0-preview.8.20352.6</SystemDrawingCommonPackageVersion>
<SystemIOPipelinesPackageVersion>5.0.0-preview.7.20326.1</SystemIOPipelinesPackageVersion> <SystemIOPipelinesPackageVersion>5.0.0-preview.8.20352.6</SystemIOPipelinesPackageVersion>
<SystemNetHttpJsonPackageVersion>5.0.0-preview.7.20326.1</SystemNetHttpJsonPackageVersion> <SystemNetHttpJsonPackageVersion>5.0.0-preview.8.20352.6</SystemNetHttpJsonPackageVersion>
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.7.20326.1</SystemNetHttpWinHttpHandlerPackageVersion> <SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.8.20352.6</SystemNetHttpWinHttpHandlerPackageVersion>
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.7.20326.1</SystemNetWebSocketsWebSocketProtocolPackageVersion> <SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.8.20352.6</SystemNetWebSocketsWebSocketProtocolPackageVersion>
<SystemReflectionMetadataPackageVersion>5.0.0-preview.7.20326.1</SystemReflectionMetadataPackageVersion> <SystemReflectionMetadataPackageVersion>5.0.0-preview.8.20352.6</SystemReflectionMetadataPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.7.20326.1</SystemRuntimeCompilerServicesUnsafePackageVersion> <SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.8.20352.6</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyCngPackageVersion> <SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyCngPackageVersion>
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyPkcsPackageVersion> <SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyPkcsPackageVersion>
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyXmlPackageVersion> <SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyXmlPackageVersion>
<SystemSecurityPermissionsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityPermissionsPackageVersion> <SystemSecurityPermissionsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityPermissionsPackageVersion>
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityPrincipalWindowsPackageVersion> <SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityPrincipalWindowsPackageVersion>
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.7.20326.1</SystemServiceProcessServiceControllerPackageVersion> <SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.8.20352.6</SystemServiceProcessServiceControllerPackageVersion>
<SystemTextEncodingsWebPackageVersion>5.0.0-preview.7.20326.1</SystemTextEncodingsWebPackageVersion> <SystemTextEncodingsWebPackageVersion>5.0.0-preview.8.20352.6</SystemTextEncodingsWebPackageVersion>
<SystemTextJsonPackageVersion>5.0.0-preview.7.20326.1</SystemTextJsonPackageVersion> <SystemTextJsonPackageVersion>5.0.0-preview.8.20352.6</SystemTextJsonPackageVersion>
<SystemThreadingChannelsPackageVersion>5.0.0-preview.7.20326.1</SystemThreadingChannelsPackageVersion> <SystemThreadingChannelsPackageVersion>5.0.0-preview.8.20352.6</SystemThreadingChannelsPackageVersion>
<SystemWindowsExtensionsPackageVersion>5.0.0-preview.7.20326.1</SystemWindowsExtensionsPackageVersion> <SystemWindowsExtensionsPackageVersion>5.0.0-preview.8.20352.6</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-preview.7.20326.1</MicrosoftNETCorePlatformsPackageVersion> <MicrosoftNETCorePlatformsPackageVersion>5.0.0-preview.8.20352.6</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-preview.7.20326.1</dotnetefPackageVersion> <dotnetefPackageVersion>5.0.0-preview.8.20353.5</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreInMemoryPackageVersion> <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreRelationalPackageVersion> <MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreSqlitePackageVersion> <MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion> <MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreToolsPackageVersion> <MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCorePackageVersion> <MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCorePackageVersion>
</PropertyGroup> </PropertyGroup>
<!-- <!--
@ -189,16 +189,16 @@
<MicrosoftCodeAnalysisCSharpPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpPackageVersion> <MicrosoftCodeAnalysisCSharpPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion> <MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.19.8</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion> <MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.19.8</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>
<MicrosoftIdentityModelLoggingPackageVersion>6.6.0</MicrosoftIdentityModelLoggingPackageVersion> <MicrosoftIdentityModelLoggingPackageVersion>5.5.0</MicrosoftIdentityModelLoggingPackageVersion>
<MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>6.6.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion> <MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>5.5.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>
<MicrosoftIdentityModelProtocolsWsFederationPackageVersion>6.6.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion> <MicrosoftIdentityModelProtocolsWsFederationPackageVersion>5.5.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion>
<MicrosoftInternalAspNetCoreH2SpecAllPackageVersion>2.2.1</MicrosoftInternalAspNetCoreH2SpecAllPackageVersion> <MicrosoftInternalAspNetCoreH2SpecAllPackageVersion>2.2.1</MicrosoftInternalAspNetCoreH2SpecAllPackageVersion>
<MicrosoftNETCoreWindowsApiSetsPackageVersion>1.0.1</MicrosoftNETCoreWindowsApiSetsPackageVersion> <MicrosoftNETCoreWindowsApiSetsPackageVersion>1.0.1</MicrosoftNETCoreWindowsApiSetsPackageVersion>
<MicrosoftOwinSecurityCookiesPackageVersion>3.0.1</MicrosoftOwinSecurityCookiesPackageVersion> <MicrosoftOwinSecurityCookiesPackageVersion>3.0.1</MicrosoftOwinSecurityCookiesPackageVersion>
<MicrosoftOwinTestingPackageVersion>3.0.1</MicrosoftOwinTestingPackageVersion> <MicrosoftOwinTestingPackageVersion>3.0.1</MicrosoftOwinTestingPackageVersion>
<MicrosoftWebAdministrationPackageVersion>11.1.0</MicrosoftWebAdministrationPackageVersion> <MicrosoftWebAdministrationPackageVersion>11.1.0</MicrosoftWebAdministrationPackageVersion>
<MicrosoftWebXdtPackageVersion>1.4.0</MicrosoftWebXdtPackageVersion> <MicrosoftWebXdtPackageVersion>1.4.0</MicrosoftWebXdtPackageVersion>
<SystemIdentityModelTokensJwtPackageVersion>6.6.0</SystemIdentityModelTokensJwtPackageVersion> <SystemIdentityModelTokensJwtPackageVersion>5.5.0</SystemIdentityModelTokensJwtPackageVersion>
<!-- Packages from 2.1/2.2 branches used for site extension build --> <!-- Packages from 2.1/2.2 branches used for site extension build -->
<MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion>2.1.1</MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion> <MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion>2.1.1</MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion>
<MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion>2.2.0</MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion> <MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion>2.2.0</MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion>
@ -221,7 +221,7 @@
<IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0</IdentityServer4EntityFrameworkStoragePackageVersion> <IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0</IdentityServer4EntityFrameworkStoragePackageVersion>
<MessagePackPackageVersion>2.1.90</MessagePackPackageVersion> <MessagePackPackageVersion>2.1.90</MessagePackPackageVersion>
<MoqPackageVersion>4.10.0</MoqPackageVersion> <MoqPackageVersion>4.10.0</MoqPackageVersion>
<MonoCecilPackageVersion>0.10.1</MonoCecilPackageVersion> <MonoCecilPackageVersion>0.11.2</MonoCecilPackageVersion>
<NewtonsoftJsonBsonPackageVersion>1.0.2</NewtonsoftJsonBsonPackageVersion> <NewtonsoftJsonBsonPackageVersion>1.0.2</NewtonsoftJsonBsonPackageVersion>
<NewtonsoftJsonPackageVersion>12.0.2</NewtonsoftJsonPackageVersion> <NewtonsoftJsonPackageVersion>12.0.2</NewtonsoftJsonPackageVersion>
<!-- Begin: STOP!!! Razor need to reference the version of JSON that our HOSTS support. --> <!-- Begin: STOP!!! Razor need to reference the version of JSON that our HOSTS support. -->

View File

@ -1,28 +0,0 @@
FROM microsoft/dotnet:2.1.0-preview1-runtime-deps-alpine
ARG USER
ARG USER_ID
ARG GROUP_ID
ARG WORKDIR
WORKDIR ${WORKDIR}
RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER"
ENV HOME "/home/$USER"
RUN apk add --no-cache \
bash \
wget \
git \
jq \
curl \
icu-libs \
openssl
USER $USER_ID:$GROUP_ID
# Disable the invariant mode (set in base image)
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
# Skip package initilization
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1

View File

@ -1,19 +0,0 @@
FROM mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine10fcdcf-20190208200917
ARG USER
ARG USER_ID
ARG GROUP_ID
ARG WORKDIR
WORKDIR ${WORKDIR}
RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER"
ENV HOME "/home/$USER"
USER $USER_ID:$GROUP_ID
# Disable the invariant mode (set in base image)
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
# Skip package initilization
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1

View File

@ -39,7 +39,7 @@
</ItemGroup> </ItemGroup>
<!-- arm64 queues for helix-matrix.yml pipeline --> <!-- arm64 queues for helix-matrix.yml pipeline -->
<ItemGroup Condition="'$(IsWindowsOnlyTest)' != 'true' AND '$(TargetArchitecture)' == 'arm64' AND '$(IsHelixDaily)' == 'true' AND '$(RunQuarantinedTests)' != 'true'"> <ItemGroup Condition="'$(IsWindowsOnlyTest)' != 'true' AND '$(TargetArchitecture)' == 'arm64' AND '$(IsHelixDaily)' == 'true'">
<HelixAvailableTargetQueue Include="Windows.10.Arm64.Open" Platform="Windows" /> <HelixAvailableTargetQueue Include="Windows.10.Arm64.Open" Platform="Windows" />
<HelixAvailableTargetQueue Include="(Debian.9.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm64v8-a12566d-20190807161036" Platform="Linux" /> <HelixAvailableTargetQueue Include="(Debian.9.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm64v8-a12566d-20190807161036" Platform="Linux" />
</ItemGroup> </ItemGroup>

View File

@ -257,8 +257,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentication", "{81250121-9B43-40B1-BF11-CE4458F2676C}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentication", "{81250121-9B43-40B1-BF11-CE4458F2676C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.HttpHandler", "WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj", "{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{630D5388-7A2F-42DD-9154-1F62A18CBB69}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{630D5388-7A2F-42DD-9154-1F62A18CBB69}"
@ -1523,18 +1521,6 @@ Global
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x64.Build.0 = Release|Any CPU {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x64.Build.0 = Release|Any CPU
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.ActiveCfg = Release|Any CPU {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.ActiveCfg = Release|Any CPU
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.Build.0 = Release|Any CPU {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.Build.0 = Release|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.ActiveCfg = Debug|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -1687,7 +1673,6 @@ Global
{5CD61479-5181-4A5B-B90F-9F34316248B3} = {81250121-9B43-40B1-BF11-CE4458F2676C} {5CD61479-5181-4A5B-B90F-9F34316248B3} = {81250121-9B43-40B1-BF11-CE4458F2676C}
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17} = {81250121-9B43-40B1-BF11-CE4458F2676C} {6B0D6C08-FC30-4822-9464-4D24FF4CDC17} = {81250121-9B43-40B1-BF11-CE4458F2676C}
{81250121-9B43-40B1-BF11-CE4458F2676C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {81250121-9B43-40B1-BF11-CE4458F2676C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10} {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
{630D5388-7A2F-42DD-9154-1F62A18CBB69} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10} {630D5388-7A2F-42DD-9154-1F62A18CBB69} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B} = {2FC10057-7A0A-4E34-8302-879925BC0102} {A062ACCE-AB0D-4569-9548-4BC0D9A9174B} = {2FC10057-7A0A-4E34-8302-879925BC0102}

View File

@ -125,8 +125,14 @@ namespace Microsoft.AspNetCore.Components
private readonly object _dummy; private readonly object _dummy;
private readonly int _dummyPrimitive; private readonly int _dummyPrimitive;
public ElementReference(string id) { throw null; } public ElementReference(string id) { throw null; }
public ElementReference(string id, Microsoft.AspNetCore.Components.ElementReferenceContext? context) { throw null; }
public Microsoft.AspNetCore.Components.ElementReferenceContext? Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
} }
public abstract partial class ElementReferenceContext
{
protected ElementReferenceContext() { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct EventCallback public readonly partial struct EventCallback
{ {
@ -468,6 +474,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; } public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; }
protected internal Microsoft.AspNetCore.Components.ElementReferenceContext? ElementReferenceContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } }
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }

View File

@ -125,8 +125,14 @@ namespace Microsoft.AspNetCore.Components
private readonly object _dummy; private readonly object _dummy;
private readonly int _dummyPrimitive; private readonly int _dummyPrimitive;
public ElementReference(string id) { throw null; } public ElementReference(string id) { throw null; }
public ElementReference(string id, Microsoft.AspNetCore.Components.ElementReferenceContext? context) { throw null; }
public Microsoft.AspNetCore.Components.ElementReferenceContext? Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
} }
public abstract partial class ElementReferenceContext
{
protected ElementReferenceContext() { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct EventCallback public readonly partial struct EventCallback
{ {
@ -467,6 +473,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; } public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; }
protected internal Microsoft.AspNetCore.Components.ElementReferenceContext? ElementReferenceContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } }
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }

View File

@ -23,13 +23,32 @@ namespace Microsoft.AspNetCore.Components
/// </remarks> /// </remarks>
public string Id { get; } public string Id { get; }
public ElementReference(string id) /// <summary>
/// Gets the <see cref="ElementReferenceContext"/> instance.
/// </summary>
public ElementReferenceContext? Context { get; }
/// <summary>
/// Instantiates a new <see cref="ElementReference" />.
/// </summary>
/// <param name="id">A unique identifier for this <see cref="ElementReference"/>.</param>
/// <param name="context">The nullable <see cref="ElementReferenceContext"/> instance.</param>
public ElementReference(string id, ElementReferenceContext? context)
{ {
Id = id; Id = id;
Context = context;
} }
internal static ElementReference CreateWithUniqueId() /// <summary>
=> new ElementReference(CreateUniqueId()); /// Instantiates a new <see cref="ElementReference"/>.
/// </summary>
/// <param name="id">A unique identifier for this <see cref="ElementReference"/>.</param>
public ElementReference(string id) : this(id, null)
{
}
internal static ElementReference CreateWithUniqueId(ElementReferenceContext? context)
=> new ElementReference(CreateUniqueId(), context);
private static string CreateUniqueId() private static string CreateUniqueId()
{ {

View File

@ -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.
namespace Microsoft.AspNetCore.Components
{
/// <summary>
/// Context for an <see cref="ElementReference"/>.
/// </summary>
public abstract class ElementReferenceContext
{
}
}

View File

@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" /> <Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" />
<Compile Include="$(ComponentsSharedSourceRoot)src\WebAssemblyJSInteropInternalCalls.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Components
static PlatformInfo() static PlatformInfo()
{ {
IsWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY")); IsWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Browser);
} }
} }
} }

View File

@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Components.Profiling
{
internal abstract class ComponentsProfiling
{
// For now, this is only intended for use on Blazor WebAssembly, and will have no effect
// when running on Blazor Server. The reason for having the ComponentsProfiling abstraction
// is so that if we later have two different implementations (one for WebAssembly, one for
// Server), the execution characteristics of calling Start/End will be unchanged and historical
// perf data will still be comparable to newer data.
public static readonly ComponentsProfiling Instance = PlatformInfo.IsWebAssembly
? new WebAssemblyComponentsProfiling()
: (ComponentsProfiling)new NoOpComponentsProfiling();
public abstract void Start([CallerMemberName] string? name = null);
public abstract void End([CallerMemberName] string? name = null);
}
}

View File

@ -0,0 +1,16 @@
// Copyright (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.Profiling
{
internal class NoOpComponentsProfiling : ComponentsProfiling
{
public override void Start(string? name)
{
}
public override void End(string? name)
{
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using WebAssembly.JSInterop;
namespace Microsoft.AspNetCore.Components.Profiling
{
// Later on, we will likely want to move this into the WebAssembly package. However it needs to
// be inlined into the Components package directly until we're ready to make the underlying
// ComponentsProfile abstraction into a public API. It's possible that this API will never become
// public, or that it will be replaced by something more standard for .NET, if it's possible to
// make that work performantly on WebAssembly.
internal class WebAssemblyComponentsProfiling : ComponentsProfiling
{
static bool IsCapturing = false;
public static void SetCapturing(bool isCapturing)
{
IsCapturing = isCapturing;
}
public override void Start(string? name)
{
if (IsCapturing)
{
InternalCalls.InvokeJSUnmarshalled<string, object, object, object>(
out _, "_blazorProfileStart", name, null, null);
}
}
public override void End(string? name)
{
if (IsCapturing)
{
InternalCalls.InvokeJSUnmarshalled<string, object, object, object>(
out _, "_blazorProfileEnd", name, null, null);
}
}
}
}

View File

@ -5,6 +5,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.RenderTree namespace Microsoft.AspNetCore.Components.RenderTree
@ -25,6 +28,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ArrayRange<RenderTreeFrame> oldTree, ArrayRange<RenderTreeFrame> oldTree,
ArrayRange<RenderTreeFrame> newTree) ArrayRange<RenderTreeFrame> newTree)
{ {
ComponentsProfiling.Instance.Start();
var editsBuffer = batchBuilder.EditsBuffer; var editsBuffer = batchBuilder.EditsBuffer;
var editsBufferStartLength = editsBuffer.Count; var editsBufferStartLength = editsBuffer.Count;
@ -32,7 +36,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count); AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count);
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count); var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
return new RenderTreeDiff(componentId, editsSegment); var result = new RenderTreeDiff(componentId, editsSegment);
ComponentsProfiling.Instance.End();
return result;
} }
public static void DisposeFrames(RenderBatchBuilder batchBuilder, ArrayRange<RenderTreeFrame> frames) public static void DisposeFrames(RenderBatchBuilder batchBuilder, ArrayRange<RenderTreeFrame> frames)
@ -43,6 +49,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl, int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl) int newStartIndex, int newEndIndexExcl)
{ {
ProfilingStart();
// This is deliberately a very large method. Parts of it could be factored out // This is deliberately a very large method. Parts of it could be factored out
// into other private methods, but doing so comes at a consequential perf cost, // into other private methods, but doing so comes at a consequential perf cost,
// because it involves so much parameter passing. You can think of the code here // because it involves so much parameter passing. You can think of the code here
@ -293,10 +300,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
diffContext.KeyedItemInfoDictionaryPool.Return(keyedItemInfos); diffContext.KeyedItemInfoDictionaryPool.Return(keyedItemInfos);
} }
} }
ProfilingEnd();
} }
private static Dictionary<object, KeyedItemInfo> BuildKeyToInfoLookup(DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) private static Dictionary<object, KeyedItemInfo> BuildKeyToInfoLookup(DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)
{ {
ProfilingStart();
var result = diffContext.KeyedItemInfoDictionaryPool.Get(); var result = diffContext.KeyedItemInfoDictionaryPool.Get();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
@ -342,6 +351,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
newStartIndex = NextSiblingIndex(frame, newStartIndex); newStartIndex = NextSiblingIndex(frame, newStartIndex);
} }
ProfilingEnd();
return result; return result;
} }
@ -374,6 +384,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl, int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl) int newStartIndex, int newEndIndexExcl)
{ {
ProfilingStart();
// The overhead of the dictionary used by AppendAttributeDiffEntriesForRangeSlow is // The overhead of the dictionary used by AppendAttributeDiffEntriesForRangeSlow is
// significant, so we want to try and do a merge-join if possible, but fall back to // significant, so we want to try and do a merge-join if possible, but fall back to
// a hash-join if not. We'll do a merge join until we hit a case we can't handle and // a hash-join if not. We'll do a merge join until we hit a case we can't handle and
@ -422,6 +433,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ref diffContext, ref diffContext,
oldStartIndex, oldEndIndexExcl, oldStartIndex, oldEndIndexExcl,
newStartIndex, newEndIndexExcl); newStartIndex, newEndIndexExcl);
ProfilingEnd();
return; return;
} }
@ -447,9 +459,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ref diffContext, ref diffContext,
oldStartIndex, oldEndIndexExcl, oldStartIndex, oldEndIndexExcl,
newStartIndex, newEndIndexExcl); newStartIndex, newEndIndexExcl);
ProfilingEnd();
return; return;
} }
} }
ProfilingEnd();
} }
private static void AppendAttributeDiffEntriesForRangeSlow( private static void AppendAttributeDiffEntriesForRangeSlow(
@ -457,6 +472,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl, int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl) int newStartIndex, int newEndIndexExcl)
{ {
ProfilingStart();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
@ -495,6 +511,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// We should have processed any additions at this point. Reset for the next batch. // We should have processed any additions at this point. Reset for the next batch.
diffContext.AttributeDiffSet.Clear(); diffContext.AttributeDiffSet.Clear();
ProfilingEnd();
} }
private static void UpdateRetainedChildComponent( private static void UpdateRetainedChildComponent(
@ -502,6 +519,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldComponentIndex, int oldComponentIndex,
int newComponentIndex) int newComponentIndex)
{ {
ProfilingStart();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
ref var oldComponentFrame = ref oldTree[oldComponentIndex]; ref var oldComponentFrame = ref oldTree[oldComponentIndex];
@ -528,6 +546,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
componentState.SetDirectParameters(newParameters); componentState.SetDirectParameters(newParameters);
} }
ProfilingEnd();
} }
private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex) private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex)
@ -550,6 +570,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldFrameIndex, int oldFrameIndex,
int newFrameIndex) int newFrameIndex)
{ {
ProfilingStart();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
ref var oldFrame = ref oldTree[oldFrameIndex]; ref var oldFrame = ref oldTree[oldFrameIndex];
@ -562,6 +583,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
InsertNewFrame(ref diffContext, newFrameIndex); InsertNewFrame(ref diffContext, newFrameIndex);
RemoveOldFrame(ref diffContext, oldFrameIndex); RemoveOldFrame(ref diffContext, oldFrameIndex);
ProfilingEnd();
return; return;
} }
@ -687,6 +709,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default: default:
throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}"); throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}");
} }
ProfilingEnd();
} }
// This should only be called for attributes that have the same name. This is an // This should only be called for attributes that have the same name. This is an
@ -696,6 +720,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldFrameIndex, int oldFrameIndex,
int newFrameIndex) int newFrameIndex)
{ {
ProfilingStart();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
ref var oldFrame = ref oldTree[oldFrameIndex]; ref var oldFrame = ref oldTree[oldFrameIndex];
@ -724,10 +749,13 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// since it was unchanged. // since it was unchanged.
newFrame = oldFrame; newFrame = oldFrame;
} }
ProfilingEnd();
} }
private static void InsertNewFrame(ref DiffContext diffContext, int newFrameIndex) private static void InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)
{ {
ProfilingStart();
var newTree = diffContext.NewTree; var newTree = diffContext.NewTree;
ref var newFrame = ref newTree[newFrameIndex]; ref var newFrame = ref newTree[newFrameIndex];
switch (newFrame.FrameType) switch (newFrame.FrameType)
@ -780,10 +808,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default: default:
throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameType}"); throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameType}");
} }
ProfilingEnd();
} }
private static void RemoveOldFrame(ref DiffContext diffContext, int oldFrameIndex) private static void RemoveOldFrame(ref DiffContext diffContext, int oldFrameIndex)
{ {
ProfilingStart();
var oldTree = diffContext.OldTree; var oldTree = diffContext.OldTree;
ref var oldFrame = ref oldTree[oldFrameIndex]; ref var oldFrame = ref oldTree[oldFrameIndex];
switch (oldFrame.FrameType) switch (oldFrame.FrameType)
@ -825,6 +855,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default: default:
throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameType}"); throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameType}");
} }
ProfilingEnd();
} }
private static int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex) private static int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex)
@ -858,6 +889,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void InitializeNewSubtree(ref DiffContext diffContext, int frameIndex) private static void InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)
{ {
ProfilingStart();
var frames = diffContext.NewTree; var frames = diffContext.NewTree;
var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLength; var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLength;
for (var i = frameIndex; i < endIndexExcl; i++) for (var i = frameIndex; i < endIndexExcl; i++)
@ -879,10 +911,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
break; break;
} }
} }
ProfilingEnd();
} }
private static void InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex) private static void InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)
{ {
ProfilingStart();
var frames = diffContext.NewTree; var frames = diffContext.NewTree;
ref var frame = ref frames[frameIndex]; ref var frame = ref frames[frameIndex];
@ -899,6 +933,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
var initialParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder); var initialParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder);
var initialParameters = new ParameterView(initialParametersLifetime, frames, frameIndex); var initialParameters = new ParameterView(initialParametersLifetime, frames, frameIndex);
childComponentState.SetDirectParameters(initialParameters); childComponentState.SetDirectParameters(initialParameters);
ProfilingEnd();
} }
private static void InitializeNewAttributeFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) private static void InitializeNewAttributeFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
@ -917,7 +952,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame) private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
{ {
var newElementReference = ElementReference.CreateWithUniqueId(); var newElementReference = ElementReference.CreateWithUniqueId(diffContext.Renderer.ElementReferenceContext);
newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id); newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id);
newFrame.ElementReferenceCaptureAction(newElementReference); newFrame.ElementReferenceCaptureAction(newElementReference);
} }
@ -943,6 +978,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void DisposeFramesInRange(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int startIndex, int endIndexExcl) private static void DisposeFramesInRange(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int startIndex, int endIndexExcl)
{ {
ProfilingStart();
for (var i = startIndex; i < endIndexExcl; i++) for (var i = startIndex; i < endIndexExcl; i++)
{ {
ref var frame = ref frames[i]; ref var frame = ref frames[i];
@ -955,6 +991,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerId); batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerId);
} }
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -996,5 +1033,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree
SiblingIndex = 0; SiblingIndex = 0;
} }
} }
// Having too many calls to ComponentsProfiling.Instance.Start/End has a measurable perf impact
// even when capturing is disabled. So, to enable detailed profiling for this class, define the
// Profile_RenderTreeDiffBuilder compiler symbol, otherwise the calls are compiled out entirely.
// Enabling detailed profiling adds about 5% to rendering benchmark times.
[Conditional("Profile_RenderTreeDiffBuilder")]
private static void ProfilingStart([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.Start(name);
[Conditional("Profile_RenderTreeDiffBuilder")]
private static void ProfilingEnd([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.End(name);
} }
} }

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -76,6 +77,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
/// </summary> /// </summary>
public abstract Dispatcher Dispatcher { get; } public abstract Dispatcher Dispatcher { get; }
/// <summary>
/// Gets or sets the <see cref="Components.ElementReferenceContext"/> associated with this <see cref="Renderer"/>,
/// if it exists.
/// </summary>
protected internal ElementReferenceContext? ElementReferenceContext { get; protected set; }
/// <summary> /// <summary>
/// Constructs a new component of the specified type. /// Constructs a new component of the specified type.
/// </summary> /// </summary>
@ -214,6 +221,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
/// </returns> /// </returns>
public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs) public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs)
{ {
ComponentsProfiling.Instance.Start();
Dispatcher.AssertAccess(); Dispatcher.AssertAccess();
if (!_eventBindings.TryGetValue(eventHandlerId, out var callback)) if (!_eventBindings.TryGetValue(eventHandlerId, out var callback))
@ -241,6 +249,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
catch (Exception e) catch (Exception e)
{ {
HandleException(e); HandleException(e);
ComponentsProfiling.Instance.End();
return Task.CompletedTask; return Task.CompletedTask;
} }
finally finally
@ -254,7 +263,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// Task completed synchronously or is still running. We already processed all of the rendering // Task completed synchronously or is still running. We already processed all of the rendering
// work that was queued so let our error handler deal with it. // work that was queued so let our error handler deal with it.
return GetErrorHandledTask(task); var result = GetErrorHandledTask(task);
ComponentsProfiling.Instance.End();
return result;
} }
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId) internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
@ -404,6 +415,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private void ProcessRenderQueue() private void ProcessRenderQueue()
{ {
ComponentsProfiling.Instance.Start();
Dispatcher.AssertAccess(); Dispatcher.AssertAccess();
if (_isBatchInProgress) if (_isBatchInProgress)
@ -418,6 +430,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
if (_batchBuilder.ComponentRenderQueue.Count == 0) if (_batchBuilder.ComponentRenderQueue.Count == 0)
{ {
ComponentsProfiling.Instance.End();
return; return;
} }
@ -429,7 +442,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
} }
var batch = _batchBuilder.ToBatch(); var batch = _batchBuilder.ToBatch();
ComponentsProfiling.Instance.Start(nameof(UpdateDisplayAsync));
updateDisplayTask = UpdateDisplayAsync(batch); updateDisplayTask = UpdateDisplayAsync(batch);
ComponentsProfiling.Instance.End(nameof(UpdateDisplayAsync));
// Fire off the execution of OnAfterRenderAsync, but don't wait for it // Fire off the execution of OnAfterRenderAsync, but don't wait for it
// if there is async work to be done. // if there is async work to be done.
@ -439,6 +454,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
// Ensure we catch errors while running the render functions of the components. // Ensure we catch errors while running the render functions of the components.
HandleException(e); HandleException(e);
ComponentsProfiling.Instance.End();
return; return;
} }
finally finally
@ -456,6 +472,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
ProcessRenderQueue(); ProcessRenderQueue();
} }
ComponentsProfiling.Instance.End();
} }
private Task InvokeRenderCompletedCalls(ArrayRange<RenderTreeDiff> updatedComponents, Task updateDisplayTask) private Task InvokeRenderCompletedCalls(ArrayRange<RenderTreeDiff> updatedComponents, Task updateDisplayTask)

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
namespace Microsoft.AspNetCore.Components.Rendering namespace Microsoft.AspNetCore.Components.Rendering
@ -56,6 +57,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment) public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
{ {
ComponentsProfiling.Instance.Start();
// A component might be in the render queue already before getting disposed by an // A component might be in the render queue already before getting disposed by an
// earlier entry in the render queue. In that case, rendering is a no-op. // earlier entry in the render queue. In that case, rendering is a no-op.
if (_componentWasDisposed) if (_componentWasDisposed)
@ -67,7 +69,9 @@ namespace Microsoft.AspNetCore.Components.Rendering
(CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree); (CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree);
CurrentRenderTree.Clear(); CurrentRenderTree.Clear();
ComponentsProfiling.Instance.Start("BuildRenderTree");
renderFragment(CurrentRenderTree); renderFragment(CurrentRenderTree);
ComponentsProfiling.Instance.End("BuildRenderTree");
var diff = RenderTreeDiffBuilder.ComputeDiff( var diff = RenderTreeDiffBuilder.ComputeDiff(
_renderer, _renderer,
@ -77,6 +81,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
CurrentRenderTree.GetFrames()); CurrentRenderTree.GetFrames());
batchBuilder.UpdatedComponentDiffs.Append(diff); batchBuilder.UpdatedComponentDiffs.Append(diff);
batchBuilder.InvalidateParameterViews(); batchBuilder.InvalidateParameterViews();
ComponentsProfiling.Instance.End();
} }
public bool TryDisposeInBatch(RenderBatchBuilder batchBuilder, [NotNullWhen(false)] out Exception? exception) public bool TryDisposeInBatch(RenderBatchBuilder batchBuilder, [NotNullWhen(false)] out Exception? exception)

View File

@ -4,6 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
namespace Microsoft.AspNetCore.Components.Rendering namespace Microsoft.AspNetCore.Components.Rendering
@ -43,6 +45,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="elementName">A value representing the type of the element.</param> /// <param name="elementName">A value representing the type of the element.</param>
public void OpenElement(int sequence, string elementName) public void OpenElement(int sequence, string elementName)
{ {
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per // We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now. // element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes) if (_hasSeenAddMultipleAttributes)
@ -53,6 +56,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count); _openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.Element(sequence, elementName)); Append(RenderTreeFrame.Element(sequence, elementName));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -61,6 +65,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary> /// </summary>
public void CloseElement() public void CloseElement()
{ {
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop(); var indexOfEntryBeingClosed = _openElementIndices.Pop();
// We might be closing an element with only attributes, run the duplicate cleanup pass // We might be closing an element with only attributes, run the duplicate cleanup pass
@ -72,6 +77,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithElementSubtreeLength(_entries.Count - indexOfEntryBeingClosed); entry = entry.WithElementSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -80,7 +86,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param> /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="markupContent">Content for the new markup frame.</param> /// <param name="markupContent">Content for the new markup frame.</param>
public void AddMarkupContent(int sequence, string? markupContent) public void AddMarkupContent(int sequence, string? markupContent)
=> Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty)); {
ProfilingStart();
Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty));
ProfilingEnd();
}
/// <summary> /// <summary>
/// Appends a frame representing text content. /// Appends a frame representing text content.
@ -88,7 +98,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param> /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="textContent">Content for the new text frame.</param> /// <param name="textContent">Content for the new text frame.</param>
public void AddContent(int sequence, string? textContent) public void AddContent(int sequence, string? textContent)
=> Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty)); {
ProfilingStart();
Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty));
ProfilingEnd();
}
/// <summary> /// <summary>
/// Appends frames representing an arbitrary fragment of content. /// Appends frames representing an arbitrary fragment of content.
@ -97,6 +111,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="fragment">Content to append.</param> /// <param name="fragment">Content to append.</param>
public void AddContent(int sequence, RenderFragment? fragment) public void AddContent(int sequence, RenderFragment? fragment)
{ {
ProfilingStart();
if (fragment != null) if (fragment != null)
{ {
// We surround the fragment with a region delimiter to indicate that the // We surround the fragment with a region delimiter to indicate that the
@ -107,6 +122,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
fragment(this); fragment(this);
CloseRegion(); CloseRegion();
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -117,10 +133,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value used by <paramref name="fragment"/>.</param> /// <param name="value">The value used by <paramref name="fragment"/>.</param>
public void AddContent<TValue>(int sequence, RenderFragment<TValue>? fragment, TValue value) public void AddContent<TValue>(int sequence, RenderFragment<TValue>? fragment, TValue value)
{ {
ProfilingStart();
if (fragment != null) if (fragment != null)
{ {
AddContent(sequence, fragment(value)); AddContent(sequence, fragment(value));
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -153,6 +171,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param> /// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, bool value) public void AddAttribute(int sequence, string name, bool value)
{ {
ProfilingStart();
AssertCanAddAttribute(); AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{ {
@ -168,6 +187,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{ {
TrackAttributeName(name); TrackAttributeName(name);
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -184,6 +204,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param> /// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, string? value) public void AddAttribute(int sequence, string name, string? value)
{ {
ProfilingStart();
AssertCanAddAttribute(); AssertCanAddAttribute();
if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component) if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component)
{ {
@ -193,6 +214,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{ {
TrackAttributeName(name); TrackAttributeName(name);
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -209,6 +231,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param> /// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, MulticastDelegate? value) public void AddAttribute(int sequence, string name, MulticastDelegate? value)
{ {
ProfilingStart();
AssertCanAddAttribute(); AssertCanAddAttribute();
if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component) if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component)
{ {
@ -218,6 +241,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{ {
TrackAttributeName(name); TrackAttributeName(name);
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -238,6 +262,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </remarks> /// </remarks>
public void AddAttribute(int sequence, string name, EventCallback value) public void AddAttribute(int sequence, string name, EventCallback value)
{ {
ProfilingStart();
AssertCanAddAttribute(); AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{ {
@ -262,6 +287,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Track the attribute name if needed since we elided the frame. // Track the attribute name if needed since we elided the frame.
TrackAttributeName(name); TrackAttributeName(name);
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -282,6 +308,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </remarks> /// </remarks>
public void AddAttribute<TArgument>(int sequence, string name, EventCallback<TArgument> value) public void AddAttribute<TArgument>(int sequence, string name, EventCallback<TArgument> value)
{ {
ProfilingStart();
AssertCanAddAttribute(); AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{ {
@ -306,6 +333,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Track the attribute name if needed since we elided the frame. // Track the attribute name if needed since we elided the frame.
TrackAttributeName(name); TrackAttributeName(name);
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -319,6 +347,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param> /// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, object? value) public void AddAttribute(int sequence, string name, object? value)
{ {
ProfilingStart();
// This looks a bit daunting because we need to handle the boxed/object version of all of the // This looks a bit daunting because we need to handle the boxed/object version of all of the
// types that AddAttribute special cases. // types that AddAttribute special cases.
if (_lastNonAttributeFrameType == RenderTreeFrameType.Element) if (_lastNonAttributeFrameType == RenderTreeFrameType.Element)
@ -371,6 +400,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// This is going to throw. Calling it just to get a consistent exception message. // This is going to throw. Calling it just to get a consistent exception message.
AssertCanAddAttribute(); AssertCanAddAttribute();
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -385,6 +415,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="frame">A <see cref="RenderTreeFrame"/> holding the name and value of the attribute.</param> /// <param name="frame">A <see cref="RenderTreeFrame"/> holding the name and value of the attribute.</param>
public void AddAttribute(int sequence, in RenderTreeFrame frame) public void AddAttribute(int sequence, in RenderTreeFrame frame)
{ {
ProfilingStart();
if (frame.FrameType != RenderTreeFrameType.Attribute) if (frame.FrameType != RenderTreeFrameType.Attribute)
{ {
throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}."); throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}.");
@ -392,6 +423,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
AssertCanAddAttribute(); AssertCanAddAttribute();
Append(frame.WithAttributeSequence(sequence)); Append(frame.WithAttributeSequence(sequence));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -401,6 +433,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="attributes">A collection of key-value pairs representing attributes.</param> /// <param name="attributes">A collection of key-value pairs representing attributes.</param>
public void AddMultipleAttributes(int sequence, IEnumerable<KeyValuePair<string, object>>? attributes) public void AddMultipleAttributes(int sequence, IEnumerable<KeyValuePair<string, object>>? attributes)
{ {
ProfilingStart();
// Calling this up-front just to make sure we validate before mutating anything. // Calling this up-front just to make sure we validate before mutating anything.
AssertCanAddAttribute(); AssertCanAddAttribute();
@ -417,6 +450,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
AddAttribute(sequence, attribute.Key, attribute.Value); AddAttribute(sequence, attribute.Key, attribute.Value);
} }
} }
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -433,6 +467,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="updatesAttributeName">The name of another attribute whose value can be updated when the event handler is executed.</param> /// <param name="updatesAttributeName">The name of another attribute whose value can be updated when the event handler is executed.</param>
public void SetUpdatesAttributeName(string updatesAttributeName) public void SetUpdatesAttributeName(string updatesAttributeName)
{ {
ProfilingStart();
if (_entries.Count == 0) if (_entries.Count == 0)
{ {
throw new InvalidOperationException("No preceding attribute frame exists."); throw new InvalidOperationException("No preceding attribute frame exists.");
@ -445,6 +480,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
prevFrame = prevFrame.WithAttributeEventUpdatesAttributeName(updatesAttributeName); prevFrame = prevFrame.WithAttributeEventUpdatesAttributeName(updatesAttributeName);
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -476,10 +512,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value for the key.</param> /// <param name="value">The value for the key.</param>
public void SetKey(object? value) public void SetKey(object? value)
{ {
ProfilingStart();
if (value == null) if (value == null)
{ {
// Null is equivalent to not having set a key, which is valuable because Razor syntax doesn't have an // Null is equivalent to not having set a key, which is valuable because Razor syntax doesn't have an
// easy way to have conditional directive attributes // easy way to have conditional directive attributes
ProfilingEnd();
return; return;
} }
@ -502,10 +540,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
default: default:
throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}."); throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}.");
} }
ProfilingEnd();
} }
private void OpenComponentUnchecked(int sequence, Type componentType) private void OpenComponentUnchecked(int sequence, Type componentType)
{ {
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per // We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now. // element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes) if (_hasSeenAddMultipleAttributes)
@ -516,6 +556,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count); _openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.ChildComponent(sequence, componentType)); Append(RenderTreeFrame.ChildComponent(sequence, componentType));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -524,6 +565,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary> /// </summary>
public void CloseComponent() public void CloseComponent()
{ {
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop(); var indexOfEntryBeingClosed = _openElementIndices.Pop();
// We might be closing a component with only attributes. Run the attribute cleanup pass // We might be closing a component with only attributes. Run the attribute cleanup pass
@ -535,6 +577,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithComponentSubtreeLength(_entries.Count - indexOfEntryBeingClosed); entry = entry.WithComponentSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -544,12 +587,14 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="elementReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param> /// <param name="elementReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param>
public void AddElementReferenceCapture(int sequence, Action<ElementReference> elementReferenceCaptureAction) public void AddElementReferenceCapture(int sequence, Action<ElementReference> elementReferenceCaptureAction)
{ {
ProfilingStart();
if (GetCurrentParentFrameType() != RenderTreeFrameType.Element) if (GetCurrentParentFrameType() != RenderTreeFrameType.Element)
{ {
throw new InvalidOperationException($"Element reference captures may only be added as children of frames of type {RenderTreeFrameType.Element}"); throw new InvalidOperationException($"Element reference captures may only be added as children of frames of type {RenderTreeFrameType.Element}");
} }
Append(RenderTreeFrame.ElementReferenceCapture(sequence, elementReferenceCaptureAction)); Append(RenderTreeFrame.ElementReferenceCapture(sequence, elementReferenceCaptureAction));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -559,6 +604,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="componentReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param> /// <param name="componentReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param>
public void AddComponentReferenceCapture(int sequence, Action<object?> componentReferenceCaptureAction) public void AddComponentReferenceCapture(int sequence, Action<object?> componentReferenceCaptureAction)
{ {
ProfilingStart();
var parentFrameIndex = GetCurrentParentFrameIndex(); var parentFrameIndex = GetCurrentParentFrameIndex();
if (!parentFrameIndex.HasValue) if (!parentFrameIndex.HasValue)
{ {
@ -572,6 +618,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue)); Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -580,6 +627,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param> /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
public void OpenRegion(int sequence) public void OpenRegion(int sequence)
{ {
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per // We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now. // element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes) if (_hasSeenAddMultipleAttributes)
@ -590,6 +638,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count); _openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.Region(sequence)); Append(RenderTreeFrame.Region(sequence));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -598,9 +647,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary> /// </summary>
public void CloseRegion() public void CloseRegion()
{ {
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop(); var indexOfEntryBeingClosed = _openElementIndices.Pop();
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed]; ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithRegionSubtreeLength(_entries.Count - indexOfEntryBeingClosed); entry = entry.WithRegionSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
} }
private void AssertCanAddAttribute() private void AssertCanAddAttribute()
@ -628,24 +679,29 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary> /// </summary>
public void Clear() public void Clear()
{ {
ProfilingStart();
_entries.Clear(); _entries.Clear();
_openElementIndices.Clear(); _openElementIndices.Clear();
_lastNonAttributeFrameType = null; _lastNonAttributeFrameType = null;
_hasSeenAddMultipleAttributes = false; _hasSeenAddMultipleAttributes = false;
_seenAttributeNames?.Clear(); _seenAttributeNames?.Clear();
ProfilingEnd();
} }
// internal because this should only be used during the post-event tree patching logic // internal because this should only be used during the post-event tree patching logic
// It's expensive because it involves copying all the subsequent memory in the array // It's expensive because it involves copying all the subsequent memory in the array
internal void InsertAttributeExpensive(int insertAtIndex, int sequence, string attributeName, object? attributeValue) internal void InsertAttributeExpensive(int insertAtIndex, int sequence, string attributeName, object? attributeValue)
{ {
ProfilingStart();
// Replicate the same attribute omission logic as used elsewhere // Replicate the same attribute omission logic as used elsewhere
if ((attributeValue == null) || (attributeValue is bool boolValue && !boolValue)) if ((attributeValue == null) || (attributeValue is bool boolValue && !boolValue))
{ {
ProfilingEnd();
return; return;
} }
_entries.InsertExpensive(insertAtIndex, RenderTreeFrame.Attribute(sequence, attributeName, attributeValue)); _entries.InsertExpensive(insertAtIndex, RenderTreeFrame.Attribute(sequence, attributeName, attributeValue));
ProfilingEnd();
} }
/// <summary> /// <summary>
@ -669,6 +725,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Internal for testing // Internal for testing
internal void ProcessDuplicateAttributes(int first) internal void ProcessDuplicateAttributes(int first)
{ {
ProfilingStart();
Debug.Assert(_hasSeenAddMultipleAttributes); Debug.Assert(_hasSeenAddMultipleAttributes);
// When AddMultipleAttributes method has been called, we need to postprocess attributes while closing // When AddMultipleAttributes method has been called, we need to postprocess attributes while closing
@ -750,6 +807,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
seenAttributeNames.Clear(); seenAttributeNames.Clear();
_hasSeenAddMultipleAttributes = false; _hasSeenAddMultipleAttributes = false;
ProfilingEnd();
} }
// Internal for testing // Internal for testing
@ -766,7 +824,22 @@ namespace Microsoft.AspNetCore.Components.Rendering
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
ProfilingStart();
_entries.Dispose(); _entries.Dispose();
ProfilingEnd();
} }
// Having too many calls to ComponentsProfiling.Instance.Start/End has a measurable perf impact
// even when capturing is disabled. So, to enable detailed profiling for this class, define the
// Profile_RenderTreeBuilder compiler symbol, otherwise the calls are compiled out entirely.
// Enabling detailed profiling adds about 5% to rendering benchmark times.
[Conditional("Profile_RenderTreeBuilder")]
private static void ProfilingStart([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.Start(name);
[Conditional("Profile_RenderTreeBuilder")]
private static void ProfilingEnd([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.End(name);
} }
} }

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
Thread capturedThread = null; Thread capturedThread = null;
var e = new ManualResetEventSlim(); var e = new ManualResetEventSlim();
// Act // Act
context.Post((_) => context.Post((_) =>
{ {
@ -766,7 +766,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
[Fact] [Fact]
[QuarantinedTest]
public async Task InvokeAsync_SyncWorkInAsyncTaskIsCompletedFirst() public async Task InvokeAsync_SyncWorkInAsyncTaskIsCompletedFirst()
{ {
// Simplified version of ServerComponentRenderingTest.CanDispatchAsyncWorkToSyncContext // Simplified version of ServerComponentRenderingTest.CanDispatchAsyncWorkToSyncContext

View File

@ -24,7 +24,6 @@
"WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj", "WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj",
"WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj", "WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj",
"WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj", "WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj",
"WebAssembly\\WebAssemblyHttpHandler\\src\\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj",
"WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj", "WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj",
"WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj",
"WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", "WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",

View File

@ -21,26 +21,4 @@
</ItemGroup> </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
<ItemGroup Condition="'$(FixupWebAssemblyHttpHandlerReference)' == 'true'">
<ProjectReference
Include="$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj"
CopyLocal="false" />
</ItemGroup>
<Target Name="_FixupReferenceToWebAssemblyHttpHandler"
Condition="'$(FixupWebAssemblyHttpHandlerReference)' == 'true'"
AfterTargets="_ResolveBlazorInputs"
BeforeTargets="_ResolveBlazorOutputs">
<!--
ProjectReference doesn't really play well with IncludeAssets behavior you get when referencing
the package with IncludeAssets="compile".
-->
<ItemGroup>
<_HttpHandlerAssembly Include="@(_BlazorUserRuntimeAssembly)"
Condition="%(_BlazorUserRuntimeAssembly.ProjectReferenceOriginalItemSpec) == '$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj'" />
<_BlazorUserRuntimeAssembly Remove="@(_HttpHandlerAssembly)" />
</ItemGroup>
</Target>
</Project> </Project>

View File

@ -64,7 +64,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
_loggerFactory, _loggerFactory,
_options, _options,
client, client,
_loggerFactory.CreateLogger<RemoteRenderer>()); _loggerFactory.CreateLogger<RemoteRenderer>(),
jsRuntime.ElementReferenceContext);
var circuitHandlers = scope.ServiceProvider.GetServices<CircuitHandler>() var circuitHandlers = scope.ServiceProvider.GetServices<CircuitHandler>()
.OrderBy(h => h.Order) .OrderBy(h => h.Order)

View File

@ -17,12 +17,15 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
private readonly ILogger<RemoteJSRuntime> _logger; private readonly ILogger<RemoteJSRuntime> _logger;
private CircuitClientProxy _clientProxy; private CircuitClientProxy _clientProxy;
public ElementReferenceContext ElementReferenceContext { get; }
public RemoteJSRuntime(IOptions<CircuitOptions> options, ILogger<RemoteJSRuntime> logger) public RemoteJSRuntime(IOptions<CircuitOptions> options, ILogger<RemoteJSRuntime> logger)
{ {
_options = options.Value; _options = options.Value;
_logger = logger; _logger = logger;
DefaultAsyncTimeout = _options.JSInteropDefaultCallTimeout; DefaultAsyncTimeout = _options.JSInteropDefaultCallTimeout;
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter()); ElementReferenceContext = new WebElementReferenceContext(this);
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter(ElementReferenceContext));
} }
internal void Initialize(CircuitClientProxy clientProxy) internal void Initialize(CircuitClientProxy clientProxy)

View File

@ -37,12 +37,15 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
CircuitOptions options, CircuitOptions options,
CircuitClientProxy client, CircuitClientProxy client,
ILogger logger) ILogger logger,
ElementReferenceContext? elementReferenceContext)
: base(serviceProvider, loggerFactory) : base(serviceProvider, loggerFactory)
{ {
_client = client; _client = client;
_options = options; _options = options;
_logger = logger; _logger = logger;
ElementReferenceContext = elementReferenceContext;
} }
public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault();

View File

@ -258,7 +258,13 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
private class TestRemoteRenderer : RemoteRenderer private class TestRemoteRenderer : RemoteRenderer
{ {
public TestRemoteRenderer(IServiceProvider serviceProvider, IClientProxy client) public TestRemoteRenderer(IServiceProvider serviceProvider, IClientProxy client)
: base(serviceProvider, NullLoggerFactory.Instance, new CircuitOptions(), new CircuitClientProxy(client, "connection"), NullLogger.Instance) : base(
serviceProvider,
NullLoggerFactory.Instance,
new CircuitOptions(),
new CircuitClientProxy(client, "connection"),
NullLogger.Instance,
null)
{ {
} }

View File

@ -437,7 +437,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
private class TestRemoteRenderer : RemoteRenderer private class TestRemoteRenderer : RemoteRenderer
{ {
public TestRemoteRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, CircuitOptions options, CircuitClientProxy client, ILogger logger) public TestRemoteRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, CircuitOptions options, CircuitClientProxy client, ILogger logger)
: base(serviceProvider, loggerFactory, options, client, logger) : base(serviceProvider, loggerFactory, options, client, logger, null)
{ {
} }

View File

@ -38,7 +38,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
NullLoggerFactory.Instance, NullLoggerFactory.Instance,
new CircuitOptions(), new CircuitOptions(),
clientProxy, clientProxy,
NullLogger.Instance); NullLogger.Instance,
null);
} }
handlers = handlers ?? Array.Empty<CircuitHandler>(); handlers = handlers ?? Array.Empty<CircuitHandler>();

View File

@ -1,22 +1,31 @@
// 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.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using Moq;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components namespace Microsoft.AspNetCore.Components
{ {
public class ElementReferenceJsonConverterTest public class ElementReferenceJsonConverterTest
{ {
private readonly ElementReferenceJsonConverter Converter = new ElementReferenceJsonConverter(); private readonly ElementReferenceContext ElementReferenceContext;
private readonly ElementReferenceJsonConverter Converter;
public ElementReferenceJsonConverterTest()
{
ElementReferenceContext = Mock.Of<ElementReferenceContext>();
Converter = new ElementReferenceJsonConverter(ElementReferenceContext);
}
[Fact] [Fact]
public void Serializing_Works() public void Serializing_Works()
{ {
// Arrange // Arrange
var elementReference = ElementReference.CreateWithUniqueId(); var elementReference = ElementReference.CreateWithUniqueId(ElementReferenceContext);
var expected = $"{{\"__internalId\":\"{elementReference.Id}\"}}"; var expected = $"{{\"__internalId\":\"{elementReference.Id}\"}}";
var memoryStream = new MemoryStream(); var memoryStream = new MemoryStream();
var writer = new Utf8JsonWriter(memoryStream); var writer = new Utf8JsonWriter(memoryStream);
@ -34,7 +43,7 @@ namespace Microsoft.AspNetCore.Components
public void Deserializing_Works() public void Deserializing_Works()
{ {
// Arrange // Arrange
var id = ElementReference.CreateWithUniqueId().Id; var id = ElementReference.CreateWithUniqueId(ElementReferenceContext).Id;
var json = $"{{\"__internalId\":\"{id}\"}}"; var json = $"{{\"__internalId\":\"{id}\"}}";
var bytes = Encoding.UTF8.GetBytes(json); var bytes = Encoding.UTF8.GetBytes(json);
var reader = new Utf8JsonReader(bytes); var reader = new Utf8JsonReader(bytes);
@ -51,7 +60,7 @@ namespace Microsoft.AspNetCore.Components
public void Deserializing_WithFormatting_Works() public void Deserializing_WithFormatting_Works()
{ {
// Arrange // Arrange
var id = ElementReference.CreateWithUniqueId().Id; var id = ElementReference.CreateWithUniqueId(ElementReferenceContext).Id;
var json = var json =
@$"{{ @$"{{
""__internalId"": ""{id}"" ""__internalId"": ""{id}""

View File

@ -11,6 +11,13 @@ namespace Microsoft.AspNetCore.Components
{ {
private static readonly JsonEncodedText IdProperty = JsonEncodedText.Encode("__internalId"); private static readonly JsonEncodedText IdProperty = JsonEncodedText.Encode("__internalId");
private readonly ElementReferenceContext _elementReferenceContext;
public ElementReferenceJsonConverter(ElementReferenceContext elementReferenceContext)
{
_elementReferenceContext = elementReferenceContext;
}
public override ElementReference Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override ElementReference Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
string id = null; string id = null;
@ -39,7 +46,7 @@ namespace Microsoft.AspNetCore.Components
throw new JsonException("__internalId is required."); throw new JsonException("__internalId is required.");
} }
return new ElementReference(id); return new ElementReference(id, _elementReferenceContext);
} }
public override void Write(Utf8JsonWriter writer, ElementReference value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, ElementReference value, JsonSerializerOptions options)

View File

@ -1,6 +1,7 @@
// 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.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace WebAssembly.JSInterop namespace WebAssembly.JSInterop
@ -21,6 +22,6 @@ namespace WebAssembly.JSInterop
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson); public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2); public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,7 @@ 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 { initializeProfiling } from './Platform/Profiling';
let renderingFailed = false; let renderingFailed = false;
let started = false; let started = false;
@ -21,6 +22,7 @@ async function boot(userOptions?: Partial<CircuitStartOptions>): Promise<void> {
throw new Error('Blazor has already started.'); throw new Error('Blazor has already started.');
} }
started = true; started = true;
initializeProfiling(null);
// Establish options to be used // Establish options to be used
const options = resolveOptions(userOptions); const options = resolveOptions(userOptions);

View File

@ -11,6 +11,7 @@ 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 { profileStart, profileEnd } from './Platform/Profiling';
let started = false; let started = false;
@ -27,7 +28,9 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
const platform = Environment.setPlatform(monoPlatform); const platform = Environment.setPlatform(monoPlatform);
window['Blazor'].platform = platform; window['Blazor'].platform = platform;
window['Blazor']._internal.renderBatch = (browserRendererId: number, batchAddress: Pointer) => { window['Blazor']._internal.renderBatch = (browserRendererId: number, batchAddress: Pointer) => {
profileStart('renderBatch');
renderBatch(browserRendererId, new SharedMemoryRenderBatch(batchAddress)); renderBatch(browserRendererId, new SharedMemoryRenderBatch(batchAddress));
profileEnd('renderBatch');
}; };
// Configure navigation via JS Interop // Configure navigation via JS Interop

View File

@ -0,0 +1,13 @@
import '@microsoft/dotnet-js-interop';
export const domFunctions = {
focus,
};
function focus(element: HTMLElement): void {
if (element instanceof HTMLElement) {
element.focus();
} else {
throw new Error('Unable to focus an invalid element.');
}
}

View File

@ -1,5 +1,7 @@
import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager'; import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager';
import { attachRootComponentToElement } from './Rendering/Renderer'; import { attachRootComponentToElement } from './Rendering/Renderer';
import { domFunctions } from './DomWrapper';
import { setProfilingEnabled } from './Platform/Profiling';
// Make the following APIs available in global scope for invocation from JS // Make the following APIs available in global scope for invocation from JS
window['Blazor'] = { window['Blazor'] = {
@ -8,5 +10,7 @@ window['Blazor'] = {
_internal: { _internal: {
attachRootComponentToElement, attachRootComponentToElement,
navigationManager: navigationManagerInternalFunctions, navigationManager: navigationManagerInternalFunctions,
domWrapper: domFunctions,
setProfilingEnabled: setProfilingEnabled,
}, },
}; };

View File

@ -5,6 +5,7 @@ import { WebAssemblyResourceLoader, LoadingResource } from '../WebAssemblyResour
import { Platform, System_Array, Pointer, System_Object, System_String } from '../Platform'; import { Platform, System_Array, Pointer, System_Object, System_String } from '../Platform';
import { loadTimezoneData } from './TimezoneDataFile'; import { loadTimezoneData } from './TimezoneDataFile';
import { WebAssemblyBootResourceType } from '../WebAssemblyStartOptions'; import { WebAssemblyBootResourceType } from '../WebAssemblyStartOptions';
import { initializeProfiling } from '../Profiling';
let mono_string_get_utf8: (managedString: System_String) => Pointer; let mono_string_get_utf8: (managedString: System_String) => Pointer;
let mono_wasm_add_assembly: (name: string, heapAddress: number, length: number) => void; let mono_wasm_add_assembly: (name: string, heapAddress: number, length: number) => void;
@ -34,6 +35,10 @@ export const monoPlatform: Platform = {
start: function start(resourceLoader: WebAssemblyResourceLoader) { start: function start(resourceLoader: WebAssemblyResourceLoader) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
attachDebuggerHotkey(resourceLoader); attachDebuggerHotkey(resourceLoader);
initializeProfiling(isCapturing => {
const setCapturingMethod = bindStaticMethod('Microsoft.AspNetCore.Components', 'Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling', 'SetCapturing');
setCapturingMethod(isCapturing);
});
// dotnet.js assumes the existence of this // dotnet.js assumes the existence of this
window['Browser'] = { window['Browser'] = {

View File

@ -0,0 +1,134 @@
import { System_String } from './Platform';
interface TimingEntry {
// To minimize overhead, don't even decode the strings that arrive from .NET. Assume they are compile-time constants
// and hence the memory address will be fixed, so we can just store the pointer value.
name: string | System_String;
type: 'start' | 'end';
timestamp: number;
}
interface TraceEvent {
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
name: string;
cat: string; // Category
ph: 'B' | 'E'; // Phase
ts: number; // Timestamp in microseconds
pid: number; // Process ID
tid: number; // Thread ID
}
let updateCapturingStateInHost: (isCapturing: boolean) => void;
let captureStartTime = 0;
const blazorProfilingEnabledKey = 'blazorProfilingEnabled';
const profilingEnabled = !!localStorage[blazorProfilingEnabledKey];
const entryLog: TimingEntry[] = [];
const openRegionsStack: (string | System_String)[] = [];
export function setProfilingEnabled(enabled: boolean) {
// We only wire up the hotkeys etc. if the following localStorage entry is present during startup
// This is to ensure we're not interfering with any other hotkeys that developers might want to
// use for different purposes, plus it gives us a single point where we can notify .NET code during
// startup about whether profiling should be enabled.
localStorage[blazorProfilingEnabledKey] = (enabled !== false);
location.reload();
}
export function initializeProfiling(setCapturingCallback: ((isCapturing: boolean) => void) | null) {
if (!profilingEnabled) {
return;
}
updateCapturingStateInHost = setCapturingCallback || (() => {});
// Attach hotkey (alt/cmd)+shift+p
const altKeyName = navigator.platform.match(/^Mac/i) ? 'Cmd' : 'Alt';
console.info(`Profiling hotkey: Shift+${altKeyName}+P (when application has focus)`);
document.addEventListener('keydown', evt => {
if (evt.shiftKey && (evt.metaKey || evt.altKey) && evt.code === 'KeyP') {
toggleCaptureEnabled();
}
});
}
export function profileStart(name: System_String | string) {
if (!captureStartTime) {
return;
}
const startTime = performance.now();
openRegionsStack.push(name);
entryLog.push({ name: name, type: 'start', timestamp: startTime });
}
export function profileEnd(name: System_String | string) {
if (!captureStartTime) {
return;
}
const endTime = performance.now();
const poppedRegionName = openRegionsStack.pop();
if (!poppedRegionName) {
throw new Error(`Profiling mismatch: tried to end profiling for '${readJsString(name)}', but the stack was empty.`);
} else if (poppedRegionName !== name) {
throw new Error(`Profiling mismatch: tried to end profiling for '${readJsString(name)}', but the top stack item was '${readJsString(poppedRegionName)}'.`);
}
entryLog.push({ name: name, type: 'end', timestamp: endTime });
}
function profileReset() {
openRegionsStack.length = 0;
entryLog.length = 0;
captureStartTime = 0;
updateCapturingStateInHost(false);
}
function profileExport() {
const traceEvents: TraceEvent[] = entryLog.map(entry => ({
name: readJsString(entry.name)!,
cat: 'PERF',
ph: entry.type === 'start' ? 'B': 'E',
ts: (entry.timestamp - captureStartTime) * 1000,
pid: 0,
tid: 0,
}));
const traceEventsJson = JSON.stringify(traceEvents);
const traceEventsBuffer = new TextEncoder().encode(traceEventsJson);
const anchorElement = document.createElement('a');
anchorElement.href = URL.createObjectURL(new Blob([traceEventsBuffer]));
anchorElement.setAttribute('download', 'trace.json');
anchorElement.click();
URL.revokeObjectURL(anchorElement.href);
}
function toggleCaptureEnabled() {
if (!captureStartTime) {
displayOverlayMessage('Started capturing performance profile...');
updateCapturingStateInHost(true);
captureStartTime = performance.now();
} else {
displayOverlayMessage('Finished capturing performance profile');
profileExport();
profileReset();
}
}
function displayOverlayMessage(message: string) {
const elem = document.createElement('div');
elem.textContent = message;
elem.setAttribute('style', 'position: absolute; z-index: 99999; font-family: \'Sans Serif\'; top: 0; left: 0; padding: 4px; font-size: 12px; background-color: purple; color: white;');
document.body.appendChild(elem);
setTimeout(() => document.body.removeChild(elem), 3000);
}
function readJsString(str: string | System_String) {
// This is expensive, so don't do it while capturing timings. Only do it as part of the export process.
return typeof str === 'string' ? str : BINDING.conv_string(str);
}
// These globals deliberately differ from our normal conventions for attaching functions inside Blazor.*
// because the intention is to minimize overhead in all reasonable ways. Having any dot-separators in the
// name would cause extra string allocations on every invocation.
window['_blazorProfileStart'] = profileStart;
window['_blazorProfileEnd'] = profileEnd;

View File

@ -6,6 +6,7 @@ import { applyCaptureIdToElement } from './ElementReferenceCapture';
import { EventFieldInfo } from './EventFieldInfo'; import { EventFieldInfo } from './EventFieldInfo';
import { dispatchEvent } from './RendererEventDispatcher'; import { dispatchEvent } from './RendererEventDispatcher';
import { attachToEventDelegator as attachNavigationManagerToEventDelegator } from '../Services/NavigationManager'; import { attachToEventDelegator as attachNavigationManagerToEventDelegator } from '../Services/NavigationManager';
import { profileEnd, profileStart } from '../Platform/Profiling';
const selectValuePropname = '_blazorSelectValue'; const selectValuePropname = '_blazorSelectValue';
const sharedTemplateElemForParsing = document.createElement('template'); const sharedTemplateElemForParsing = document.createElement('template');
const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g'); const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g');
@ -40,6 +41,8 @@ export class BrowserRenderer {
} }
public updateComponent(batch: RenderBatch, componentId: number, edits: ArrayBuilderSegment<RenderTreeEdit>, referenceFrames: ArrayValues<RenderTreeFrame>): void { public updateComponent(batch: RenderBatch, componentId: number, edits: ArrayBuilderSegment<RenderTreeEdit>, referenceFrames: ArrayValues<RenderTreeFrame>): void {
profileStart('updateComponent');
const element = this.childComponentLocations[componentId]; const element = this.childComponentLocations[componentId];
if (!element) { if (!element) {
throw new Error(`No element is currently associated with component ${componentId}`); throw new Error(`No element is currently associated with component ${componentId}`);
@ -67,6 +70,8 @@ export class BrowserRenderer {
if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) { if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) {
activeElementBefore.focus(); activeElementBefore.focus();
} }
profileEnd('updateComponent');
} }
public disposeComponent(componentId: number) { public disposeComponent(componentId: number) {

View File

@ -14,6 +14,14 @@ namespace Microsoft.AspNetCore.Components
public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
} }
public static partial class ElementReferenceExtensions
{
public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference) { throw null; }
}
public partial class WebElementReferenceContext : Microsoft.AspNetCore.Components.ElementReferenceContext
{
public WebElementReferenceContext(Microsoft.JSInterop.IJSRuntime jsRuntime) { }
}
} }
namespace Microsoft.AspNetCore.Components.Forms namespace Microsoft.AspNetCore.Components.Forms
{ {
@ -53,7 +61,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected TValue CurrentValue { get { throw null; } set { } } protected TValue CurrentValue { get { throw null; } set { } }
protected string? CurrentValueAsString { get { throw null; } set { } } protected string? CurrentValueAsString { get { throw null; } set { } }
protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
[System.Diagnostics.CodeAnalysis.MaybeNullAttribute] [System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
[System.Diagnostics.CodeAnalysis.AllowNullAttribute] [System.Diagnostics.CodeAnalysis.AllowNullAttribute]
@ -63,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Linq.Expressions.Expression<System.Func<TValue>>? ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Linq.Expressions.Expression<System.Func<TValue>>? ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected virtual void Dispose(bool disposing) { } protected virtual void Dispose(bool disposing) { }
protected virtual string? FormatValueAsString(TValue value) { throw null; } protected virtual string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
void System.IDisposable.Dispose() { } void System.IDisposable.Dispose() { }
protected abstract bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage); protected abstract bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage);
@ -80,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override string FormatValueAsString(TValue value) { throw null; } protected override string FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; } protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
} }
public partial class InputNumber<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue> public partial class InputNumber<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
@ -89,9 +97,34 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override string? FormatValueAsString(TValue value) { throw null; } protected override string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; } protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
} }
public partial class InputRadioGroup<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputRadioGroup() { }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public Microsoft.AspNetCore.Components.RenderFragment? ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
}
public partial class InputRadio<TValue> : Microsoft.AspNetCore.Components.ComponentBase
{
public InputRadio() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
public System.Collections.Generic.IReadOnlyDictionary<string, object>? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
[System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
[System.Diagnostics.CodeAnalysis.AllowNullAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
}
public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue> public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{ {
public InputSelect() { } public InputSelect() { }

View File

@ -14,6 +14,14 @@ namespace Microsoft.AspNetCore.Components
public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
} }
public static partial class ElementReferenceExtensions
{
public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference) { throw null; }
}
public partial class WebElementReferenceContext : Microsoft.AspNetCore.Components.ElementReferenceContext
{
public WebElementReferenceContext(Microsoft.JSInterop.IJSRuntime jsRuntime) { }
}
} }
namespace Microsoft.AspNetCore.Components.Forms namespace Microsoft.AspNetCore.Components.Forms
{ {
@ -51,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected TValue CurrentValue { get { throw null; } set { } } protected TValue CurrentValue { get { throw null; } set { } }
protected string? CurrentValueAsString { get { throw null; } set { } } protected string? CurrentValueAsString { get { throw null; } set { } }
protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
@ -88,6 +96,29 @@ namespace Microsoft.AspNetCore.Components.Forms
protected override string? FormatValueAsString(TValue value) { throw null; } protected override string? FormatValueAsString(TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; } protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; }
} }
public partial class InputRadioGroup<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputRadioGroup() { }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public Microsoft.AspNetCore.Components.RenderFragment? ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; }
}
public partial class InputRadio<TValue> : Microsoft.AspNetCore.Components.ComponentBase
{
public InputRadio() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
public System.Collections.Generic.IReadOnlyDictionary<string, object>? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
}
public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue> public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{ {
public InputSelect() { } public InputSelect() { }

View File

@ -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.
namespace Microsoft.AspNetCore.Components
{
internal static class DomWrapperInterop
{
private const string Prefix = "Blazor._internal.domWrapper.";
public const string Focus = Prefix + "focus";
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) .NET 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
{
public static class ElementReferenceExtensions
{
/// <summary>
/// Gives focus to an element given its <see cref="ElementReference"/>.
/// </summary>
/// <param name="elementReference">A reference to the element to focus.</param>
/// <returns>The <see cref="ValueTask"/> representing the asynchronous focus operation.</returns>
public static ValueTask FocusAsync(this ElementReference elementReference)
{
var jsRuntime = elementReference.GetJSRuntime();
if (jsRuntime == null)
{
throw new InvalidOperationException("No JavaScript runtime found.");
}
return jsRuntime.InvokeVoidAsync(DomWrapperInterop.Focus, elementReference);
}
internal static IJSRuntime GetJSRuntime(this ElementReference elementReference)
{
if (!(elementReference.Context is WebElementReferenceContext context))
{
throw new InvalidOperationException("ElementReference has not been configured correctly.");
}
return context.JSRuntime;
}
}
}

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// <summary> /// <summary>
/// Gets the <see cref="FieldIdentifier"/> for the bound value. /// Gets the <see cref="FieldIdentifier"/> for the bound value.
/// </summary> /// </summary>
protected FieldIdentifier FieldIdentifier { get; set; } protected internal FieldIdentifier FieldIdentifier { get; set; }
/// <summary> /// <summary>
/// Gets or sets the current value of the input. /// Gets or sets the current value of the input.
@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary> /// </summary>
/// <param name="value">The value to format.</param> /// <param name="value">The value to format.</param>
/// <returns>A string representation of the value.</returns> /// <returns>A string representation of the value.</returns>
protected virtual string? FormatValueAsString(TValue value) protected virtual string? FormatValueAsString([AllowNull] TValue value)
=> value?.ToString(); => value?.ToString();
/// <summary> /// <summary>

View File

@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Components.Forms
} }
/// <inheritdoc /> /// <inheritdoc />
protected override string FormatValueAsString(TValue value) protected override string FormatValueAsString([AllowNull] TValue value)
{ {
switch (value) switch (value)
{ {

View File

@ -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;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace Microsoft.AspNetCore.Components.Forms
{
internal static class InputExtensions
{
public static bool TryParseSelectableValueFromString<TValue>(this InputBase<TValue> input, string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
{
try
{
if (BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue))
{
result = parsedValue;
validationErrorMessage = null;
return true;
}
else
{
result = default;
validationErrorMessage = $"The {input.FieldIdentifier.FieldName} field is not valid.";
return false;
}
}
catch (InvalidOperationException ex)
{
throw new InvalidOperationException($"{input.GetType()} does not support the type '{typeof(TValue)}'.", ex);
}
}
}
}

View File

@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary> /// </summary>
/// <param name="value">The value to format.</param> /// <param name="value">The value to format.</param>
/// <returns>A string representation of the value.</returns> /// <returns>A string representation of the value.</returns>
protected override string? FormatValueAsString(TValue value) protected override string? FormatValueAsString([AllowNull] TValue value)
{ {
// Avoiding a cast to IFormattable to avoid boxing. // Avoiding a cast to IFormattable to avoid boxing.
switch (value) switch (value)

View File

@ -0,0 +1,82 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// An input component used for selecting a value from a group of choices.
/// </summary>
public class InputRadio<TValue> : ComponentBase
{
/// <summary>
/// Gets context for this <see cref="InputRadio{TValue}"/>.
/// </summary>
internal InputRadioContext? Context { get; private set; }
/// <summary>
/// Gets or sets a collection of additional attributes that will be applied to the input element.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
/// <summary>
/// Gets or sets the value of this input.
/// </summary>
[AllowNull]
[MaybeNull]
[Parameter]
public TValue Value { get; set; } = default;
/// <summary>
/// Gets or sets the name of the parent input radio group.
/// </summary>
[Parameter] public string? Name { get; set; }
[CascadingParameter] private InputRadioContext? CascadedContext { get; set; }
private string GetCssClass(string fieldClass)
{
if (AdditionalAttributes != null &&
AdditionalAttributes.TryGetValue("class", out var @class) &&
!string.IsNullOrEmpty(Convert.ToString(@class)))
{
return $"{@class} {fieldClass}";
}
return fieldClass;
}
/// <inheritdoc />
protected override void OnParametersSet()
{
Context = string.IsNullOrEmpty(Name) ? CascadedContext : CascadedContext?.FindContextInAncestors(Name);
if (Context == null)
{
throw new InvalidOperationException($"{GetType()} must have an ancestor {typeof(InputRadioGroup<TValue>)} " +
$"with a matching 'Name' property, if specified.");
}
}
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
Debug.Assert(Context != null);
builder.OpenElement(0, "input");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", GetCssClass(Context.FieldClass));
builder.AddAttribute(3, "type", "radio");
builder.AddAttribute(4, "name", Context.GroupName);
builder.AddAttribute(5, "value", BindConverter.FormatValue(Value?.ToString()));
builder.AddAttribute(6, "checked", Context.CurrentValue?.Equals(Value));
builder.AddAttribute(7, "onchange", Context.ChangeEventCallback);
builder.CloseElement();
}
}
}

View File

@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// Describes context for an <see cref="InputRadio{TValue}"/> component.
/// </summary>
internal class InputRadioContext
{
private readonly InputRadioContext? _parentContext;
/// <summary>
/// Gets the name of the input radio group.
/// </summary>
public string GroupName { get; }
/// <summary>
/// Gets the current selected value in the input radio group.
/// </summary>
public object? CurrentValue { get; }
/// <summary>
/// Gets a css class indicating the validation state of input radio elements.
/// </summary>
public string FieldClass { get; }
/// <summary>
/// Gets the event callback to be invoked when the selected value is changed.
/// </summary>
public EventCallback<ChangeEventArgs> ChangeEventCallback { get; }
/// <summary>
/// Instantiates a new <see cref="InputRadioContext" />.
/// </summary>
/// <param name="parentContext">The parent <see cref="InputRadioContext" />.</param>
/// <param name="groupName">The name of the input radio group.</param>
/// <param name="currentValue">The current selected value in the input radio group.</param>
/// <param name="fieldClass">The css class indicating the validation state of input radio elements.</param>
/// <param name="changeEventCallback">The event callback to be invoked when the selected value is changed.</param>
public InputRadioContext(
InputRadioContext? parentContext,
string groupName,
object? currentValue,
string fieldClass,
EventCallback<ChangeEventArgs> changeEventCallback)
{
_parentContext = parentContext;
GroupName = groupName;
CurrentValue = currentValue;
FieldClass = fieldClass;
ChangeEventCallback = changeEventCallback;
}
/// <summary>
/// Finds an <see cref="InputRadioContext"/> in the context's ancestors with the matching <paramref name="groupName"/>.
/// </summary>
/// <param name="groupName">The group name of the ancestor <see cref="InputRadioContext"/>.</param>
/// <returns>The <see cref="InputRadioContext"/>, or <c>null</c> if none was found.</returns>
public InputRadioContext? FindContextInAncestors(string groupName)
=> string.Equals(GroupName, groupName) ? this : _parentContext?.FindContextInAncestors(groupName);
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// Groups child <see cref="InputRadio{TValue}"/> components.
/// </summary>
public class InputRadioGroup<TValue> : InputBase<TValue>
{
private readonly string _defaultGroupName = Guid.NewGuid().ToString("N");
private InputRadioContext? _context;
/// <summary>
/// Gets or sets the child content to be rendering inside the <see cref="InputRadioGroup{TValue}"/>.
/// </summary>
[Parameter] public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Gets or sets the name of the group.
/// </summary>
[Parameter] public string? Name { get; set; }
[CascadingParameter] private InputRadioContext? CascadedContext { get; set; }
/// <inheritdoc />
protected override void OnParametersSet()
{
var groupName = !string.IsNullOrEmpty(Name) ? Name : _defaultGroupName;
var fieldClass = EditContext.FieldCssClass(FieldIdentifier);
var changeEventCallback = EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString);
_context = new InputRadioContext(CascadedContext, groupName, CurrentValue, fieldClass, changeEventCallback);
}
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
Debug.Assert(_context != null);
builder.OpenComponent<CascadingValue<InputRadioContext>>(2);
builder.AddAttribute(3, "IsFixed", true);
builder.AddAttribute(4, "Value", _context);
builder.AddAttribute(5, "ChildContent", ChildContent);
builder.CloseComponent();
}
/// <inheritdoc />
protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
=> this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage);
}
}

View File

@ -1,9 +1,7 @@
// 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.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms namespace Microsoft.AspNetCore.Components.Forms
@ -13,8 +11,6 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary> /// </summary>
public class InputSelect<TValue> : InputBase<TValue> public class InputSelect<TValue> : InputBase<TValue>
{ {
private static readonly Type? _nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue));
/// <summary> /// <summary>
/// Gets or sets the child content to be rendering inside the select element. /// Gets or sets the child content to be rendering inside the select element.
/// </summary> /// </summary>
@ -34,31 +30,6 @@ namespace Microsoft.AspNetCore.Components.Forms
/// <inheritdoc /> /// <inheritdoc />
protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage) protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
{ => this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage);
if (typeof(TValue) == typeof(string))
{
result = (TValue)(object?)value;
validationErrorMessage = null;
return true;
}
else if (typeof(TValue).IsEnum || (_nullableUnderlyingType != null && _nullableUnderlyingType.IsEnum))
{
var success = BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue);
if (success)
{
result = parsedValue;
validationErrorMessage = null;
return true;
}
else
{
result = default;
validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
return false;
}
}
throw new InvalidOperationException($"{GetType()} does not support the type '{typeof(TValue)}'.");
}
} }
} }

View File

@ -1,3 +1,4 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Server.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Server.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Web.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -0,0 +1,18 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.JSInterop;
namespace Microsoft.AspNetCore.Components
{
public class WebElementReferenceContext : ElementReferenceContext
{
internal IJSRuntime JSRuntime { get; }
public WebElementReferenceContext(IJSRuntime jsRuntime)
{
JSRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
}
}
}

View File

@ -0,0 +1,138 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Xunit;
namespace Microsoft.AspNetCore.Components.Forms
{
public class InputRadioTest
{
[Fact]
public async Task ThrowsOnFirstRenderIfInputRadioHasNoGroup()
{
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithoutGroup(null)
};
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => RenderAndGetTestInputComponentAsync(rootComponent));
Assert.Contains($"must have an ancestor", ex.Message);
}
[Fact]
public async Task GroupGeneratesNameGuidWhenInvalidNameSupplied()
{
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithGroup(null, () => model.TestEnum)
};
var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent);
Assert.All(inputRadioComponents, inputRadio => Assert.True(Guid.TryParseExact(inputRadio.GroupName, "N", out _)));
}
[Fact]
public async Task RadioInputContextExistsWhenValidNameSupplied()
{
var groupName = "group";
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithGroup(groupName, () => model.TestEnum)
};
var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent);
Assert.All(inputRadioComponents, inputRadio => Assert.Equal(groupName, inputRadio.GroupName));
}
private static RenderFragment RadioButtonsWithoutGroup(string name) => (builder) =>
{
foreach (var selectedValue in (TestEnum[])Enum.GetValues(typeof(TestEnum)))
{
builder.OpenComponent<TestInputRadio>(0);
builder.AddAttribute(1, "Name", name);
builder.AddAttribute(2, "Value", selectedValue);
builder.CloseComponent();
}
};
private static RenderFragment RadioButtonsWithGroup(string name, Expression<Func<TestEnum>> valueExpression) => (builder) =>
{
builder.OpenComponent<InputRadioGroup<TestEnum>>(0);
builder.AddAttribute(1, "Name", name);
builder.AddAttribute(2, "ValueExpression", valueExpression);
builder.AddAttribute(2, "ChildContent", new RenderFragment((childBuilder) =>
{
foreach (var value in (TestEnum[])Enum.GetValues(typeof(TestEnum)))
{
childBuilder.OpenComponent<TestInputRadio>(0);
childBuilder.AddAttribute(1, "Value", value);
childBuilder.CloseComponent();
}
}));
builder.CloseComponent();
};
private static IEnumerable<TestInputRadio> FindInputRadioComponents(CapturedBatch batch)
=> batch.ReferenceFrames
.Where(f => f.FrameType == RenderTreeFrameType.Component)
.Select(f => f.Component)
.OfType<TestInputRadio>();
private static async Task<IEnumerable<TestInputRadio>> RenderAndGetTestInputComponentAsync(TestInputRadioHostComponent<TestEnum> rootComponent)
{
var testRenderer = new TestRenderer();
var componentId = testRenderer.AssignRootComponentId(rootComponent);
await testRenderer.RenderRootComponentAsync(componentId);
return FindInputRadioComponents(testRenderer.Batches.Single());
}
private enum TestEnum
{
One,
Two,
Three
}
private class TestModel
{
public TestEnum TestEnum { get; set; }
}
private class TestInputRadio : InputRadio<TestEnum>
{
public string GroupName => Context.GroupName;
}
private class TestInputRadioHostComponent<TValue> : AutoRenderComponent
{
public EditContext EditContext { get; set; }
public RenderFragment InnerContent { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenComponent<CascadingValue<EditContext>>(0);
builder.AddAttribute(1, "Value", EditContext);
builder.AddAttribute(2, "ChildContent", InnerContent);
builder.CloseComponent();
}
}
}
}

View File

@ -90,6 +90,88 @@ namespace Microsoft.AspNetCore.Components.Forms
Assert.Null(inputSelectComponent.CurrentValue); Assert.Null(inputSelectComponent.CurrentValue);
} }
// See: https://github.com/dotnet/aspnetcore/issues/9939
[Fact]
public async Task ParsesCurrentValueWhenUsingNotNullableGuid()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableGuid
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
var guid = Guid.NewGuid();
inputSelectComponent.CurrentValueAsString = guid.ToString();
// Assert
Assert.Equal(guid, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/issues/9939
[Fact]
public async Task ParsesCurrentValueWhenUsingNullableGuid()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid?>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NullableGuid
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
var guid = Guid.NewGuid();
inputSelectComponent.CurrentValueAsString = guid.ToString();
// Assert
Assert.Equal(guid, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/pull/19562
[Fact]
public async Task ParsesCurrentValueWhenUsingNotNullableInt()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableInt
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
inputSelectComponent.CurrentValueAsString = "42";
// Assert
Assert.Equal(42, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/pull/19562
[Fact]
public async Task ParsesCurrentValueWhenUsingNullableInt()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int?>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NullableInt
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
inputSelectComponent.CurrentValueAsString = "42";
// Assert
Assert.Equal(42, inputSelectComponent.CurrentValue);
}
private static TestInputSelect<TValue> FindInputSelectComponent<TValue>(CapturedBatch batch) private static TestInputSelect<TValue> FindInputSelectComponent<TValue>(CapturedBatch batch)
=> batch.ReferenceFrames => batch.ReferenceFrames
.Where(f => f.FrameType == RenderTreeFrameType.Component) .Where(f => f.FrameType == RenderTreeFrameType.Component)
@ -117,6 +199,14 @@ namespace Microsoft.AspNetCore.Components.Forms
public TestEnum NotNullableEnum { get; set; } public TestEnum NotNullableEnum { get; set; }
public TestEnum? NullableEnum { get; set; } public TestEnum? NullableEnum { get; set; }
public Guid NotNullableGuid { get; set; }
public Guid? NullableGuid { get; set; }
public int NotNullableInt { get; set; }
public int? NullableInt { get; set; }
} }
class TestInputSelect<TValue> : InputSelect<TValue> class TestInputSelect<TValue> : InputSelect<TValue>

View File

@ -9,6 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\WebAssemblyJSInteropInternalCalls.cs" />
<Reference Include="Microsoft.JSInterop" /> <Reference Include="Microsoft.JSInterop" />
</ItemGroup> </ItemGroup>

View File

@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
var parameters = ParameterView.FromDictionary(new Dictionary<string, object> var parameters = ParameterView.FromDictionary(new Dictionary<string, object>
{ {
[_action] = RemoteAuthenticationActions.LogInCallback, [_action] = RemoteAuthenticationActions.LogInCallback,
[_onLogInSucceded] = new EventCallbackFactory().Create< RemoteAuthenticationState>( [_onLogInSucceded] = new EventCallbackFactory().Create<RemoteAuthenticationState>(
remoteAuthenticator, remoteAuthenticator,
(state) => loggingSucceededCalled = true), (state) => loggingSucceededCalled = true),
}); });

View File

@ -23,11 +23,6 @@
Private="false" Private="false"
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" /> Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
<!-- Tracking removing using https://github.com/dotnet/aspnetcore/issues/22283 -->
<ProjectReference
Include="..\..\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj"
IncludeAssets="compile" />
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" /> <SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" />
</ItemGroup> </ItemGroup>

View File

@ -34,6 +34,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
// The WebAssembly renderer registers and unregisters itself with the static registry // The WebAssembly renderer registers and unregisters itself with the static registry
_webAssemblyRendererId = RendererRegistry.Add(this); _webAssemblyRendererId = RendererRegistry.Add(this);
_logger = loggerFactory.CreateLogger<WebAssemblyRenderer>(); _logger = loggerFactory.CreateLogger<WebAssemblyRenderer>();
ElementReferenceContext = DefaultWebAssemblyJSRuntime.Instance.ElementReferenceContext;
} }
public override Dispatcher Dispatcher => NullDispatcher.Instance; public override Dispatcher Dispatcher => NullDispatcher.Instance;

View File

@ -10,9 +10,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
{ {
internal static readonly DefaultWebAssemblyJSRuntime Instance = new DefaultWebAssemblyJSRuntime(); internal static readonly DefaultWebAssemblyJSRuntime Instance = new DefaultWebAssemblyJSRuntime();
public ElementReferenceContext ElementReferenceContext { get; }
private DefaultWebAssemblyJSRuntime() private DefaultWebAssemblyJSRuntime()
{ {
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter()); ElementReferenceContext = new WebElementReferenceContext(this);
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter(ElementReferenceContext));
} }
#pragma warning disable IDE0051 // Remove unused private members. Invoked via Mono's JS interop mechanism (invoke_method) #pragma warning disable IDE0051 // Remove unused private members. Invoked via Mono's JS interop mechanism (invoke_method)

View File

@ -1,7 +1,10 @@
// Copyright (c) .NET 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;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Blazor.Rendering namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
{ {
public class RenderRegistryTest public class RenderRegistryTest
{ {

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
<TargetFramework>netstandard2.1</TargetFramework>
<PackageId>$(MSBuildProjectName)</PackageId>
<AssemblyName>System.Net.Http.WebAssemblyHttpHandler</AssemblyName>
<AssemblyVersion>0.2.2.0</AssemblyVersion>
<ProduceOnlyReferenceAssembly>true</ProduceOnlyReferenceAssembly>
<StrongNameKeyId>Open</StrongNameKeyId>
</PropertyGroup>
<ItemGroup>
<NuspecProperty Include="OutputPath=$(OutputPath)" />
</ItemGroup>
</Project>

View File

@ -1,11 +0,0 @@
using System;
using System.Net.Http;
namespace System.Net.Http
{
public partial class WebAssemblyHttpHandler : System.Net.Http.HttpMessageHandler
{
public WebAssemblyHttpHandler() { }
protected override System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { throw null; }
}
}

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
$CommonMetadataElements$
<dependencies>
<group targetFramework=".NETStandard2.1" />
</dependencies>
</metadata>
<files>
$CommonFileElements$
<file src="$OutputPath$System.Net.Http.WebAssemblyHttpHandler.dll" target="lib\netstandard2.1\System.Net.Http.WebAssemblyHttpHandler.dll" />
</files>
</package>

View File

@ -4,8 +4,6 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly> <UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -4,8 +4,6 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly> <UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -40,13 +40,12 @@ namespace Wasm.Performance.Driver
return 1; return 1;
} }
if (stressRunSeconds < 1) if (stressRunSeconds < 0)
{ {
Console.Error.WriteLine("Stress run duration must be a positive integer."); Console.Error.WriteLine("Stress run duration must be a positive integer.");
return 1; return 1;
} }
else if (stressRunSeconds > 0)
if (stressRunSeconds > 0)
{ {
isStressRun = true; isStressRun = true;

View File

@ -15,7 +15,13 @@ namespace Wasm.Performance.Driver
{ {
const int SeleniumPort = 4444; const int SeleniumPort = 4444;
static bool RunHeadlessBrowser = true; static bool RunHeadlessBrowser = true;
static bool PoolForBrowserLogs = false;
static bool PoolForBrowserLogs =
#if DEBUG
true;
#else
false;
#endif
private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationToken cancellationToken) private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationToken cancellationToken)
{ {

View File

@ -8,6 +8,7 @@
<!-- WebDriver is not strong-named, so this test project cannot be strong named either. --> <!-- WebDriver is not strong-named, so this test project cannot be strong named either. -->
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<IsTestAssetProject>true</IsTestAssetProject> <IsTestAssetProject>true</IsTestAssetProject>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -9,7 +9,7 @@ The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. T
Here are the commands you would need to run it locally inside docker: Here are the commands you would need to run it locally inside docker:
1. `dotnet publish -c Release -r linux-x64 Driver/Wasm.Performance.Driver.csproj` 1. `dotnet publish -c Release Driver/Wasm.Performance.Driver.csproj`
2. `docker build -t blazor-local -f ./local.dockerfile . ` 2. `docker build -t blazor-local -f ./local.dockerfile . `
3. `docker run -it blazor-local` 3. `docker run -it blazor-local`

View File

@ -0,0 +1,122 @@
@page "/gridrendering"
@inject IJSRuntime JSRuntime
@using Wasm.Performance.TestApp.Shared.FastGrid
<h1>20 x 200 Grid</h1>
<fieldset>
<select id="render-mode" @bind="selectedRenderMode">
<option>@RenderMode.FastGrid</option>
<option>@RenderMode.PlainTable</option>
<option>@RenderMode.ComplexTable</option>
</select>
<button id="show" @onclick="Show">Show</button>
<button id="hide" @onclick="Hide">Hide</button>
@if (forecasts != null)
{
<button id="change-page" @onclick="ChangePage">Switch pages</button>
}
</fieldset>
@if (forecasts == null)
{
<p><em>(No data assigned)</em></p>
}
else if (selectedRenderMode == RenderMode.FastGrid)
{
<p>FastGrid represents a minimal, optimized implementation of a grid.</p>
<Grid Data="@forecasts">
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
</Grid>
}
else if (selectedRenderMode == RenderMode.PlainTable)
{
<p>PlainTable represents a minimal but not optimized implementation of a grid.</p>
<Wasm.Performance.TestApp.Shared.PlainTable.TableComponent Data="@forecasts" Columns="@Columns" />
}
else if (selectedRenderMode == RenderMode.ComplexTable)
{
<p>ComplexTable represents a maximal, not optimized implementation of a grid, using a wide range of Blazor features at once.</p>
<Wasm.Performance.TestApp.Shared.ComplexTable.TableComponent Data="@forecasts" Columns="@Columns" />
}
@code {
enum RenderMode { PlainTable, ComplexTable, FastGrid }
private RenderMode selectedRenderMode = RenderMode.FastGrid;
private WeatherForecast[] forecasts;
public List<string> Columns { get; set; } = new List<string>
{
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
};
private static string[] sampleSummaries = new[] { "Balmy", "Chilly", "Freezing", "Bracing" };
private static WeatherForecast[] staticSampleDataPage1 = Enumerable.Range(0, 200).Select(CreateSampleDataItem).ToArray();
private static WeatherForecast[] staticSampleDataPage2 = Enumerable.Range(200, 200).Select(CreateSampleDataItem).ToArray();
private static WeatherForecast CreateSampleDataItem(int index) => new WeatherForecast
{
Date = DateTime.Now.Date.AddDays(index),
Summary = sampleSummaries[index % sampleSummaries.Length],
TemperatureC = index,
};
void Show()
{
forecasts = staticSampleDataPage1;
}
void Hide()
{
forecasts = null;
}
void ChangePage()
{
forecasts = (forecasts == staticSampleDataPage1) ? staticSampleDataPage2 : staticSampleDataPage1;
}
protected override void OnAfterRender(bool firstRender)
{
BenchmarkEvent.Send(JSRuntime, "Finished rendering table");
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

View File

@ -0,0 +1,59 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<td @attributes="@Attributes"
@onclick="@(() => OnClick.Invoke(CellIndex))"
>
@switch (Field)
{
case "Date":
@Item.Date.ToShortDateString()
break;
case "TemperatureC":
@Item.TemperatureC
break;
case "TemperatureF":
@Item.TemperatureF
break;
case "Summary":
@Item.Summary
break;
}
</td>
@code {
[Parameter]
public WeatherForecast Item { get; set; }
[CascadingParameter]
public TableComponent ParentTable { get; set; }
[Parameter]
public string Field { get; set; }
[Parameter]
public int CellIndex { get; set; }
[Parameter]
public int RowIndex { get; set; }
[Parameter]
public bool Selected { get; set; }
[Parameter]
public string FormatString { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
private protected Dictionary<string, object> Attributes
{
get
{
var attributes = new Dictionary<string, object>();
attributes["tabindex"] = CellIndex;
return attributes;
}
}
}

View File

@ -0,0 +1,39 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<tr class="complex-table-row" style="@rowStyle">
@foreach (var item in Columns)
{
<Cell Item="@Item"
Field="@item"
CellIndex="1"
RowIndex="2"
Selected="@isSelected"
FormatString="foo"
OnClick="@OnCellClick">
</Cell>
}
</tr>
@code {
private bool isSelected = false;
private string rowStyle => isSelected ? "background-color: lightblue;" : "";
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
Task OnCellClick(int args)
{
isSelected = !isSelected;
return OnClick.Invoke(args);
}
}

View File

@ -0,0 +1,19 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
@foreach (var item in Data)
{
<Row Item="@item" Columns="@Columns"
OnClick="@OnClick"></Row>
}
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,46 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<table class="table">
<thead>
<tr>
@foreach (var item in Columns)
{
<th>@item</th>
}
</tr>
</thead>
<tbody>
<CascadingValue Value="@this">
<RowCollection Data="@Data"
Columns="@Columns"
OnClick="@RefreshComponent"></RowCollection>
</CascadingValue>
</tbody>
</table>
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
DateTime t1;
DateTime t2;
Task RefreshComponent(int index)
{
t1 = DateTime.Now;
StateHasChanged();
return Task.CompletedTask;
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
t2 = DateTime.Now;
Console.WriteLine("Refresh Time " + (t2 - t1).TotalMilliseconds);
}
return base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -0,0 +1,48 @@
@typeparam TRowData
<CascadingValue IsFixed="true" Value="this">@ChildContent</CascadingValue>
<table @attributes="@Attributes">
<thead>
<tr>
@foreach (var col in columns)
{
col.RenderHeader(__builder);
}
</tr>
</thead>
<tbody>
@foreach (var item in Data)
{
<tr @key="item.GetHashCode()" class="@(RowClass?.Invoke(item))">
@foreach (var col in columns)
{
col.RenderCell(__builder, item);
}
</tr>
}
</tbody>
</table>
@code {
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> Attributes { get; set; }
[Parameter] public ICollection<TRowData> Data { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public Func<TRowData, string> RowClass { get; set; }
private List<GridColumn<TRowData>> columns = new List<GridColumn<TRowData>>();
internal void AddColumn(GridColumn<TRowData> column)
{
columns.Add(column);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// On the first render, we collect the list of columns, then we have to render them.
StateHasChanged();
}
}
}

View File

@ -0,0 +1,23 @@
@typeparam TRowData
@using Microsoft.AspNetCore.Components.Rendering
@code {
[CascadingParameter] public Grid<TRowData> OwnerGrid { get; set; }
[Parameter] public string Title { get; set; }
[Parameter] public TRowData RowData { get; set; }
[Parameter] public RenderFragment<TRowData> ChildContent { get; set; }
protected override void OnInitialized()
{
OwnerGrid.AddColumn(this);
}
internal void RenderHeader(RenderTreeBuilder __builder)
{
<th>@Title</th>
}
internal void RenderCell(RenderTreeBuilder __builder, TRowData rowData)
{
<td>@ChildContent(rowData)</td>
}
}

View File

@ -6,7 +6,8 @@
<a href="renderlist">RenderList</a> | <a href="renderlist">RenderList</a> |
<a href="json">JSON</a> | <a href="json">JSON</a> |
<a href="orgchart">OrgChart</a> | <a href="orgchart">OrgChart</a> |
<a href="timer">Timer</a> <a href="timer">Timer</a> |
<a href="gridrendering">Grid</a>
<hr /> <hr />

View File

@ -0,0 +1,30 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<td @onclick="@(() => OnClick.Invoke(1))">
@switch (Field)
{
case "Date":
@Item.Date.ToShortDateString()
break;
case "TemperatureC":
@Item.TemperatureC
break;
case "TemperatureF":
@Item.TemperatureF
break;
case "Summary":
@Item.Summary
break;
}
</td>
@code {
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public string Field { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,35 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<tr style="@rowStyle">
@foreach (var item in Columns)
{
<Cell Item="@Item"
Field="@item"
OnClick="@OnCellClick">
</Cell>
}
</tr>
@code {
private bool isSelected = false;
private string rowStyle => isSelected ? "background-color: lightblue;" : "";
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
Task OnCellClick(int args)
{
isSelected = !isSelected;
return OnClick.Invoke(args);
}
}

View File

@ -0,0 +1,19 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
@foreach (var item in Data)
{
<Row Item="@item" Columns="@Columns"
OnClick="@OnClick"></Row>
}
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,44 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<table class="table">
<thead>
<tr>
@foreach (var item in Columns)
{
<th>@item</th>
}
</tr>
</thead>
<tbody>
<RowCollection Data="@Data"
Columns="@Columns"
OnClick="@RefreshComponent"></RowCollection>
</tbody>
</table>
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
DateTime t1;
DateTime t2;
Task RefreshComponent(int index)
{
t1 = DateTime.Now;
StateHasChanged();
return Task.CompletedTask;
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
t2 = DateTime.Now;
Console.WriteLine("Refresh Time " + (t2 - t1).TotalMilliseconds);
}
return base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -0,0 +1,105 @@
import { group, benchmark, setup, teardown } from './lib/minibench/minibench.js';
import { receiveEvent } from './util/BenchmarkEvents.js';
import { BlazorApp } from './util/BlazorApp.js';
import { setInputValue } from './util/DOM.js';
group('Grid', () => {
let app;
setup(async () => {
app = new BlazorApp();
await app.start();
app.navigateTo('gridrendering');
});
teardown(() => {
app.dispose();
});
benchmark('PlainTable: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'PlainTable', false),
descriptor: {
name: 'blazorwasm/render-plaintable-from-blank',
description: 'Time to render plain table from blank (ms)'
}
});
benchmark('PlainTable: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'PlainTable', true),
descriptor: {
name: 'blazorwasm/render-plaintable-switch-pages',
description: 'Time to render plain table change of page (ms)'
}
});
benchmark('ComplexTable: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'ComplexTable', false),
descriptor: {
name: 'blazorwasm/render-complextable-from-blank',
description: 'Time to render complex table from blank (ms)'
}
});
benchmark('ComplexTable: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'ComplexTable', true),
descriptor: {
name: 'blazorwasm/render-complextable-switch-pages',
description: 'Time to render complex table change of page (ms)'
}
});
benchmark('FastGrid: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'FastGrid', false),
descriptor: {
name: 'blazorwasm/render-fastgrid-from-blank',
description: 'Time to render fast grid from blank (ms)'
}
});
benchmark('FastGrid: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'FastGrid', true),
descriptor: {
name: 'blazorwasm/render-fastgrid-switch-pages',
description: 'Time to render fast grid change of page (ms)'
}
});
});
async function prepare(app, renderMode, populateTable) {
const renderModeSelect = app.window.document.querySelector('#render-mode');
setInputValue(renderModeSelect, renderMode);
if (populateTable) {
let nextRenderCompletion = receiveEvent('Finished rendering table');
app.window.document.querySelector(populateTable ? '#show' : '#hide').click();
await nextRenderCompletion;
}
}
async function measureRenderGridFromBlank(app) {
const appDocument = app.window.document;
let nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#hide').click();
await nextRenderCompletion;
if (appDocument.querySelectorAll('tbody tr').length !== 0) {
throw new Error('Wrong number of rows rendered');
}
nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#show').click();
await nextRenderCompletion;
if (appDocument.querySelectorAll('tbody tr').length !== 200) {
throw new Error('Wrong number of rows rendered');
}
}
async function measureRenderGridSwitchPages(app) {
const appDocument = app.window.document;
let nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#change-page').click();
await nextRenderCompletion;
}

View File

@ -4,6 +4,7 @@ import './appStartup.js';
import './renderList.js'; import './renderList.js';
import './jsonHandling.js'; import './jsonHandling.js';
import './orgChart.js'; import './orgChart.js';
import './grid.js';
import { getBlazorDownloadSize } from './blazorDownloadSize.js'; import { getBlazorDownloadSize } from './blazorDownloadSize.js';
new HtmlUI('E2E Performance', '#display'); new HtmlUI('E2E Performance', '#display');

View File

@ -20,10 +20,11 @@ ADD https://api.github.com/repos/dotnet/aspnetcore/git/ref/heads/${gitBranch} /a
RUN git init \ RUN git init \
&& git fetch https://github.com/aspnet/aspnetcore ${gitBranch} \ && git fetch https://github.com/aspnet/aspnetcore ${gitBranch} \
&& git reset --hard FETCH_HEAD \ && git reset --hard FETCH_HEAD \
&& git submodule update --init && git submodule update --init \
&& git remote add origin https://github.com/aspnet/aspnetcore
RUN ./restore.sh RUN ./restore.sh
RUN .dotnet/dotnet publish -c Release -r linux-x64 -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj RUN .dotnet/dotnet publish -c Release --no-restore -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj
RUN chmod +x /app/Wasm.Performance.Driver RUN chmod +x /app/Wasm.Performance.Driver
WORKDIR /app WORKDIR /app

View File

@ -3,7 +3,7 @@ FROM selenium/standalone-chrome:3.141.59-mercury as final
ENV StressRunDuration=0 ENV StressRunDuration=0
WORKDIR /app WORKDIR /app
COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./ COPY ./Driver/bin/Release/net5.0/linux-x64/publish ./
COPY ./exec.sh ./ COPY ./exec.sh ./
ENTRYPOINT [ "bash", "./exec.sh" ] ENTRYPOINT [ "bash", "./exec.sh" ]

View File

@ -6,6 +6,7 @@ using BasicTestApp;
using BasicTestApp.HttpClientTest; using BasicTestApp.HttpClientTest;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI; using OpenQA.Selenium.Support.UI;
using TestServer; using TestServer;
@ -44,6 +45,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23366")]
public void CanSendAndReceiveBytes() public void CanSendAndReceiveBytes()
{ {
IssueRequest("/subdir/api/data"); IssueRequest("/subdir/api/data");

View File

@ -7,6 +7,7 @@ using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Moq; using Moq;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI; using OpenQA.Selenium.Support.UI;
@ -506,6 +507,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")]
public void CanBindTextboxNullableDouble() public void CanBindTextboxNullableDouble()
{ {
var target = Browser.FindElement(By.Id("textbox-nullable-double")); var target = Browser.FindElement(By.Id("textbox-nullable-double"));

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
} }
[Fact] [Fact]
[QuarantinedTest] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23366")]
public void CanRenderTextOnlyComponent() public void CanRenderTextOnlyComponent()
{ {
var appElement = Browser.MountTestComponent<TextOnlyComponent>(); var appElement = Browser.MountTestComponent<TextOnlyComponent>();
@ -400,6 +400,26 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("Clicks: 2", () => inputElement.GetAttribute("value")); Browser.Equal("Clicks: 2", () => inputElement.GetAttribute("value"));
} }
[Fact]
public void CanUseFocusExtensionToFocusElement()
{
var appElement = Browser.MountTestComponent<ElementFocusComponent>();
var buttonElement = appElement.FindElement(By.Id("focus-button"));
// Make sure the input element isn't focused when the test begins; we don't want
// the test to pass just because the input started as the focused element
Browser.NotEqual("focus-input", getFocusedElementId);
// Click the button whose callback focuses the input element
buttonElement.Click();
// Verify that the input element is focused
Browser.Equal("focus-input", getFocusedElementId);
// A local helper that gets the ID of the focused element.
string getFocusedElementId() => Browser.SwitchTo().ActiveElement().GetAttribute("id");
}
[Fact] [Fact]
public void CanCaptureReferencesToDynamicallyAddedElements() public void CanCaptureReferencesToDynamicallyAddedElements()
{ {
@ -464,6 +484,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
} }
[Fact] [Fact]
[QuarantinedTest]
public void CanRenderMarkupBlocks() public void CanRenderMarkupBlocks()
{ {
var appElement = Browser.MountTestComponent<MarkupBlockComponent>(); var appElement = Browser.MountTestComponent<MarkupBlockComponent>();

View File

@ -6,6 +6,7 @@ using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using OpenQA.Selenium; using OpenQA.Selenium;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
@ -50,6 +51,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")]
public void ShowsErrorNotification_OnError_Reload() public void ShowsErrorNotification_OnError_Reload()
{ {
var causeErrorButton = Browser.Exists(By.Id("throw-simple-exception")); var causeErrorButton = Browser.Exists(By.Id("throw-simple-exception"));

Some files were not shown because too many files have changed in this diff Show More