diff --git a/.azure/pipelines/ci-public.yml b/.azure/pipelines/ci-public.yml
index cb521dc97a9a..f7d33e8e4c09 100644
--- a/.azure/pipelines/ci-public.yml
+++ b/.azure/pipelines/ci-public.yml
@@ -414,7 +414,7 @@ stages:
jobName: Linux_musl_x64_build
jobDisplayName: "Build: Linux Musl x64"
agentOs: Linux
- container: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode
+ container: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-build-amd64
buildArgs:
--arch x64
--os-name linux-musl
@@ -449,7 +449,7 @@ stages:
jobDisplayName: "Build: Linux Musl ARM"
agentOs: Linux
useHostedUbuntu: false
- container: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm-alpine
+ container: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-build-amd64
buildArgs:
--arch arm
--os-name linux-musl
@@ -483,7 +483,7 @@ stages:
jobDisplayName: "Build: Linux Musl ARM64"
agentOs: Linux
useHostedUbuntu: false
- container: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64-alpine
+ container: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-build-amd64
buildArgs:
--arch arm64
--os-name linux-musl
@@ -612,7 +612,7 @@ stages:
parameters:
platform:
name: 'Managed'
- container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8'
+ container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-build-amd64'
buildScript: './eng/build.sh $(_PublishArgs) --no-build-nodejs --no-build-repo-tasks $(_InternalRuntimeDownloadArgs)'
skipPublishValidation: true
jobProperties:
diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml
index 61d5c7a3657a..107fcdef9ff3 100644
--- a/.azure/pipelines/ci.yml
+++ b/.azure/pipelines/ci.yml
@@ -143,12 +143,8 @@ extends:
tsa:
enabled: true
containers:
- alpine319WithNode:
- image: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode
- mariner20CrossArmAlpine:
- image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm-alpine
- mariner20CrossArm64Alpine:
- image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64-alpine
+ azureLinux30Net8BuildAmd64:
+ image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-build-amd64
stages:
- stage: build
displayName: Build
@@ -483,7 +479,7 @@ extends:
jobName: Linux_musl_x64_build
jobDisplayName: "Build: Linux Musl x64"
agentOs: Linux
- container: alpine319WithNode
+ container: azureLinux30Net8BuildAmd64
buildArgs:
--arch x64
--os-name linux-musl
@@ -518,7 +514,7 @@ extends:
jobDisplayName: "Build: Linux Musl ARM"
agentOs: Linux
useHostedUbuntu: false
- container: mariner20CrossArmAlpine
+ container: azureLinux30Net8BuildAmd64
buildArgs:
--arch arm
--os-name linux-musl
@@ -552,7 +548,7 @@ extends:
jobDisplayName: "Build: Linux Musl ARM64"
agentOs: Linux
useHostedUbuntu: false
- container: mariner20CrossArm64Alpine
+ container: azureLinux30Net8BuildAmd64
buildArgs:
--arch arm64
--os-name linux-musl
diff --git a/.azure/pipelines/identitymodel-helix-matrix.yml b/.azure/pipelines/identitymodel-helix-matrix.yml
index 55f0f8dd8063..91be7f22c42f 100644
--- a/.azure/pipelines/identitymodel-helix-matrix.yml
+++ b/.azure/pipelines/identitymodel-helix-matrix.yml
@@ -84,7 +84,7 @@ extends:
filePath: $(Build.SourcesDirectory)/eng/scripts/SetupIdentitySources.ps1
arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -IdentityModelPackageSource $(Build.StagingDirectory)
# Build the shared framework
- - script: ./eng/build.cmd -ci -nobl -all -pack -arch x64
+ - script: ./eng/build.cmd -ci -nativeToolsOnMachine -nobl -all -pack -arch x64
/p:CrossgenOutput=false /p:IsIdentityModelTestJob=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Build shared fx
# -noBuildRepoTasks -noBuildNative -noBuild to avoid repeating work done in the previous step.
@@ -98,4 +98,4 @@ extends:
artifacts:
- name: Helix_logs
path: artifacts/log/
- publishOnError: true
\ No newline at end of file
+ publishOnError: true
diff --git a/NuGet.config b/NuGet.config
index fc0223c67220..d263ff7579a8 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -6,10 +6,10 @@
-
+
-
+
@@ -30,10 +30,10 @@
-
+
-
+
diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props
index 9db2ec00437b..af5cc98a0d47 100644
--- a/eng/Baseline.Designer.props
+++ b/eng/Baseline.Designer.props
@@ -2,117 +2,117 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
@@ -120,138 +120,138 @@
- 8.0.12
+ 8.0.13
-
-
+
+
-
-
+
+
-
-
+
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
-
-
-
+
+
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
+
+
@@ -259,83 +259,83 @@
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
@@ -343,58 +343,58 @@
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
@@ -403,7 +403,7 @@
- 8.0.12
+ 8.0.13
@@ -411,71 +411,71 @@
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
-
-
+
+
- 8.0.12
+ 8.0.13
@@ -491,27 +491,27 @@
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
@@ -520,79 +520,79 @@
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
+
+
-
-
+
+
-
-
+
+
- 8.0.12
+ 8.0.13
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -600,83 +600,83 @@
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
-
-
-
+
+
+
+
- 8.0.12
+ 8.0.13
@@ -685,64 +685,64 @@
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
@@ -764,29 +764,29 @@
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
@@ -802,48 +802,48 @@
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
-
-
+
+
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
@@ -853,7 +853,7 @@
- 8.0.12
+ 8.0.13
@@ -862,79 +862,79 @@
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
-
+
-
+
-
+
-
+
-
+
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
@@ -943,7 +943,7 @@
-
+
@@ -951,17 +951,17 @@
-
+
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
@@ -979,18 +979,18 @@
- 8.0.12
+ 8.0.13
- 8.0.12
+ 8.0.13
-
+
- 8.0.12
+ 8.0.13
diff --git a/eng/Baseline.xml b/eng/Baseline.xml
index 7de065eab47a..9efbb290ef60 100644
--- a/eng/Baseline.xml
+++ b/eng/Baseline.xml
@@ -4,110 +4,110 @@ This file contains a list of all the packages and their versions which were rele
Update this list when preparing for a new patch.
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index c65d291b0c2b..216f52bfdd7d 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -9,37 +9,37 @@
-->
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- 1bdfaaeddf567214d363aa2396fd4874abf204cc
+ d00955545e8afc997726aead9b0e6103b1ceade6
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -121,9 +121,9 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
5535e31a712343a63f5d7d796cd874e563e5ac14
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -139,7 +139,7 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -185,13 +185,13 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
5535e31a712343a63f5d7d796cd874e563e5ac14
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://github.com/dotnet/source-build-externals
- c7cb4da26e74ef645e3e98fcb4534a7d66247a82
+ dc30cd1ec22f198d658e011c14525d4d65873991
@@ -275,17 +275,17 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
81cabf2857a01351e5ab578947c7403a5b128ad1
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -316,31 +316,31 @@
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.
-->
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
https://github.com/dotnet/xdt
9a1c3e1b7f0c8763d4c96e593961a61a72679a7b
-
+
https://github.com/dotnet/source-build-reference-packages
- f9542c50beaefc38dd9d7ec9ea38d54fd154f21a
+ d73fc552386797322e84fa9b2ef5eaa5369de83c
@@ -368,9 +368,9 @@
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- eba546b0f0d448e0176a2222548fd7a2fbf464c0
+ 1584e493603cfc4e9b36b77d6d4afe97de6363f9
https://github.com/dotnet/winforms
diff --git a/eng/Versions.props b/eng/Versions.props
index 6f7e8ca85634..a4361bbfd167 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -8,7 +8,7 @@
8
0
- 13
+ 14
true
@@ -67,12 +67,12 @@
8.0.2
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13-servicing.25066.9
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14-servicing.25111.18
8.0.0
8.0.1
8.0.0
@@ -93,7 +93,7 @@
8.0.0
8.0.0
8.0.0
- 8.0.13-servicing.25066.9
+ 8.0.14-servicing.25111.18
8.0.1
8.0.1
8.0.1
@@ -109,7 +109,7 @@
8.0.0
8.0.2
8.0.0
- 8.0.13-servicing.25066.9
+ 8.0.14-servicing.25111.18
8.0.1
8.0.1
8.0.1
@@ -129,9 +129,9 @@
8.0.0
8.0.0
8.0.0
- 8.0.13-servicing.25066.9
+ 8.0.14-servicing.25111.18
- 8.0.13-servicing.25066.9
+ 8.0.14-servicing.25111.18
8.0.0
8.0.1
@@ -143,14 +143,14 @@
8.1.0-preview.23604.1
8.1.0-preview.23604.1
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
- 8.0.13
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
+ 8.0.14
4.8.0-7.24574.2
4.8.0-7.24574.2
@@ -166,9 +166,9 @@
8.0.0-beta.25060.1
8.0.0-beta.25060.1
- 8.0.0-alpha.1.25060.2
+ 8.0.0-alpha.1.25104.1
- 8.0.0-alpha.1.25060.2
+ 8.0.0-alpha.1.25081.5
2.0.0-beta-23228-03
diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml
index 41bbb915736a..9f4c600ac094 100644
--- a/eng/common/templates/steps/source-build.yml
+++ b/eng/common/templates/steps/source-build.yml
@@ -44,7 +44,7 @@ steps:
# in the default public locations.
internalRuntimeDownloadArgs=
if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then
- internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)'
+ internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)'
fi
buildConfig=Release
diff --git a/eng/scripts/InstallJdk.ps1 b/eng/scripts/InstallJdk.ps1
index 0872f241a982..1ba711b5eaa4 100644
--- a/eng/scripts/InstallJdk.ps1
+++ b/eng/scripts/InstallJdk.ps1
@@ -22,8 +22,7 @@ $installDir = "$repoRoot\.tools\jdk\win-x64\"
$javacExe = "$installDir\bin\javac.exe"
$tempDir = "$repoRoot\obj"
if (-not $JdkVersion) {
- $globalJson = Get-Content "$repoRoot\global.json" | ConvertFrom-Json
- $JdkVersion = $globalJson.'native-tools'.jdk
+ $JdkVersion = "11.0.24"
}
if (Test-Path $javacExe) {
diff --git a/eng/targets/Helix.Common.props b/eng/targets/Helix.Common.props
index ea3801bb8226..8a0fdf3481d3 100644
--- a/eng/targets/Helix.Common.props
+++ b/eng/targets/Helix.Common.props
@@ -29,7 +29,7 @@
-
+
diff --git a/eng/targets/Helix.targets b/eng/targets/Helix.targets
index f9d0cf5ef518..70e01877befa 100644
--- a/eng/targets/Helix.targets
+++ b/eng/targets/Helix.targets
@@ -17,7 +17,7 @@
$(HelixQueueAlmaLinux8);
- $(HelixQueueAlpine316);
+ $(HelixQueueAlpine318);
$(HelixQueueDebian12);
$(HelixQueueFedora40);
$(HelixQueueMariner);
diff --git a/global.json b/global.json
index 69227aa61ad7..3002fbd32cbe 100644
--- a/global.json
+++ b/global.json
@@ -1,9 +1,9 @@
{
"sdk": {
- "version": "8.0.112"
+ "version": "8.0.113"
},
"tools": {
- "dotnet": "8.0.112",
+ "dotnet": "8.0.113",
"runtimes": {
"dotnet/x86": [
"$(MicrosoftNETCoreBrowserDebugHostTransportVersion)"
@@ -29,6 +29,6 @@
"Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.25060.1"
},
"native-tools": {
- "jdk": "11.0.24"
+ "jdk": "latest"
}
}
diff --git a/src/Components/Components/src/CascadingValueSource.cs b/src/Components/Components/src/CascadingValueSource.cs
index dbf9a4662265..3645b17bed39 100644
--- a/src/Components/Components/src/CascadingValueSource.cs
+++ b/src/Components/Components/src/CascadingValueSource.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components;
@@ -96,7 +97,16 @@ public Task NotifyChangedAsync()
{
tasks.Add(dispatcher.InvokeAsync(() =>
{
- foreach (var subscriber in subscribers)
+ var subscribersBuffer = new ComponentStateBuffer();
+ var subscribersCount = subscribers.Count;
+ var subscribersCopy = subscribersCount <= ComponentStateBuffer.Capacity
+ ? subscribersBuffer[..subscribersCount]
+ : new ComponentState[subscribersCount];
+ subscribers.CopyTo(subscribersCopy);
+
+ // We iterate over a copy of the list because new subscribers might get
+ // added or removed during change notification
+ foreach (var subscriber in subscribersCopy)
{
subscriber.NotifyCascadingValueChanged(ParameterViewLifetime.Unbound);
}
@@ -174,4 +184,15 @@ void ICascadingValueSupplier.Unsubscribe(ComponentState subscriber, in Cascading
}
}
}
+
+ [InlineArray(Capacity)]
+ internal struct ComponentStateBuffer
+ {
+ public const int Capacity = 64;
+#pragma warning disable IDE0051 // Remove unused private members
+#pragma warning disable IDE0044 // Add readonly modifier
+ private ComponentState _values;
+#pragma warning restore IDE0044 // Add readonly modifier
+#pragma warning restore IDE0051 // Remove unused private members
+ }
}
diff --git a/src/Components/Components/test/CascadingParameterTest.cs b/src/Components/Components/test/CascadingParameterTest.cs
index a99baeb96833..411ed14a5e07 100644
--- a/src/Components/Components/test/CascadingParameterTest.cs
+++ b/src/Components/Components/test/CascadingParameterTest.cs
@@ -634,6 +634,61 @@ public async Task CanTriggerUpdatesOnCascadingValuesFromServiceProvider()
await cascadingValueSource.NotifyChangedAsync(new MyParamType("Nobody is listening, but this shouldn't be an error"));
}
+ [Fact]
+ public async Task CanAddSubscriberDuringChangeNotification()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var paramValue = new MyParamType("Initial value");
+ var cascadingValueSource = new CascadingValueSource(paramValue, isFixed: false);
+ services.AddCascadingValue(_ => cascadingValueSource);
+ var renderer = new TestRenderer(services.BuildServiceProvider());
+ var component = new ConditionallyRenderSubscriberComponent()
+ {
+ RenderWhenEqualTo = "Final value",
+ };
+
+ // Act/Assert: Initial render
+ var componentId = await renderer.Dispatcher.InvokeAsync(() => renderer.AssignRootComponentId(component));
+ renderer.RenderRootComponent(componentId);
+ var firstBatch = renderer.Batches.Single();
+ var diff = firstBatch.DiffsByComponentId[componentId].Single();
+ Assert.Collection(diff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
+ AssertFrame.Text(
+ firstBatch.ReferenceFrames[edit.ReferenceFrameIndex],
+ "CascadingParameter=Initial value");
+ });
+ Assert.Equal(1, component.NumRenders);
+
+ // Act: Second render
+ paramValue.ChangeValue("Final value");
+ await cascadingValueSource.NotifyChangedAsync();
+ var secondBatch = renderer.Batches[1];
+ var diff2 = secondBatch.DiffsByComponentId[componentId].Single();
+
+ // Assert: Subscriber can get added during change notification and receive the cascading value
+ AssertFrame.Text(
+ secondBatch.ReferenceFrames[diff2.Edits[0].ReferenceFrameIndex],
+ "CascadingParameter=Final value");
+ Assert.Equal(2, component.NumRenders);
+
+ // Assert: Subscriber can get added during change notification and receive the cascading value
+ var nestedComponent = FindComponent(secondBatch, out var nestedComponentId);
+ var nestedComponentDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single();
+ Assert.Collection(nestedComponentDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
+ AssertFrame.Text(
+ secondBatch.ReferenceFrames[edit.ReferenceFrameIndex],
+ "CascadingParameter=Final value");
+ });
+ Assert.Equal(1, nestedComponent.NumRenders);
+ }
+
[Fact]
public async Task AfterSupplyingValueThroughNotifyChanged_InitialValueFactoryIsNotUsed()
{
@@ -772,6 +827,40 @@ public void CanUseTryAddPatternForCascadingValuesInServiceCollection_CascadingVa
Assert.Equal(2, services.Count());
}
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(CascadingValueSource.ComponentStateBuffer.Capacity - 1)]
+ [InlineData(CascadingValueSource.ComponentStateBuffer.Capacity)]
+ [InlineData(CascadingValueSource.ComponentStateBuffer.Capacity + 1)]
+ [InlineData(CascadingValueSource.ComponentStateBuffer.Capacity * 2)]
+ public async Task CanHaveManySubscribers(int numSubscribers)
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var paramValue = new MyParamType("Initial value");
+ var cascadingValueSource = new CascadingValueSource(paramValue, isFixed: false);
+ services.AddCascadingValue(_ => cascadingValueSource);
+ var renderer = new TestRenderer(services.BuildServiceProvider());
+ var components = Enumerable.Range(0, numSubscribers).Select(_ => new SimpleSubscriberComponent()).ToArray();
+
+ // Act/Assert: Initial render
+ foreach (var component in components)
+ {
+ await renderer.Dispatcher.InvokeAsync(() => renderer.AssignRootComponentId(component));
+ component.TriggerRender();
+ Assert.Equal(1, component.NumRenders);
+ }
+
+ // Act/Assert: All components re-render when the cascading value changes
+ paramValue.ChangeValue("Final value");
+ await cascadingValueSource.NotifyChangedAsync();
+ foreach (var component in components)
+ {
+ Assert.Equal(2, component.NumRenders);
+ }
+ }
+
private class SingleDeliveryValue(string text)
{
public string Text => text;
@@ -861,6 +950,43 @@ public void AttemptIllegalAccessToLastParameterView()
}
}
+ class ConditionallyRenderSubscriberComponent : AutoRenderComponent
+ {
+ public int NumRenders { get; private set; }
+
+ public SimpleSubscriberComponent NestedSubscriber { get; private set; }
+
+ [Parameter] public string RenderWhenEqualTo { get; set; }
+
+ [CascadingParameter] MyParamType CascadingParameter { get; set; }
+
+ protected override void BuildRenderTree(RenderTreeBuilder builder)
+ {
+ NumRenders++;
+ builder.AddContent(0, $"CascadingParameter={CascadingParameter}");
+
+ if (string.Equals(RenderWhenEqualTo, CascadingParameter.ToString(), StringComparison.OrdinalIgnoreCase))
+ {
+ builder.OpenComponent(1);
+ builder.AddComponentReferenceCapture(2, component => NestedSubscriber = component as SimpleSubscriberComponent);
+ builder.CloseComponent();
+ }
+ }
+ }
+
+ class SimpleSubscriberComponent : AutoRenderComponent
+ {
+ public int NumRenders { get; private set; }
+
+ [CascadingParameter] MyParamType CascadingParameter { get; set; }
+
+ protected override void BuildRenderTree(RenderTreeBuilder builder)
+ {
+ NumRenders++;
+ builder.AddContent(0, $"CascadingParameter={CascadingParameter}");
+ }
+ }
+
class SingleDeliveryParameterConsumerComponent : AutoRenderComponent
{
public int NumSetParametersCalls { get; private set; }
diff --git a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
index b00505fabb53..fadf9de6547c 100644
--- a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
+++ b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
@@ -98,12 +98,12 @@ This package is an internal implementation of the .NET Core SDK and is not meant
PkgMicrosoft_NETCore_App_Runtime_$(RuntimeIdentifier.Replace('.', '_'))
$(TargetOsName)
- linux
+ linux
$(TargetRuntimeIdentifier.Substring(0,$(TargetRuntimeIdentifier.IndexOf('-'))))
x64
$(BuildArchitecture)
diff --git a/src/Identity/Core/src/SignInManager.cs b/src/Identity/Core/src/SignInManager.cs
index b5659b329854..66f06c4d3465 100644
--- a/src/Identity/Core/src/SignInManager.cs
+++ b/src/Identity/Core/src/SignInManager.cs
@@ -162,8 +162,21 @@ public virtual async Task CanSignInAsync(TUser user)
public virtual async Task RefreshSignInAsync(TUser user)
{
var auth = await Context.AuthenticateAsync(AuthenticationScheme);
- IList claims = Array.Empty();
+ if (!auth.Succeeded || auth.Principal?.Identity?.IsAuthenticated != true)
+ {
+ Logger.LogError("RefreshSignInAsync prevented because the user is not currently authenticated. Use SignInAsync instead for initial sign in.");
+ return;
+ }
+ var authenticatedUserId = UserManager.GetUserId(auth.Principal);
+ var newUserId = await UserManager.GetUserIdAsync(user);
+ if (authenticatedUserId == null || authenticatedUserId != newUserId)
+ {
+ Logger.LogError("RefreshSignInAsync prevented because currently authenticated user has a different UserId. Use SignInAsync instead to change users.");
+ return;
+ }
+
+ IList claims = Array.Empty();
var authenticationMethod = auth?.Principal?.FindFirst(ClaimTypes.AuthenticationMethod);
var amr = auth?.Principal?.FindFirst("amr");
diff --git a/src/Identity/test/Identity.Test/SignInManagerTest.cs b/src/Identity/test/Identity.Test/SignInManagerTest.cs
index d1072676138a..73fe6d6be218 100644
--- a/src/Identity/test/Identity.Test/SignInManagerTest.cs
+++ b/src/Identity/test/Identity.Test/SignInManagerTest.cs
@@ -592,38 +592,38 @@ public async Task CanExternalSignIn(bool isPersistent, bool supportsLockout)
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
- public async Task CanResignIn(
- // Suppress warning that says theory methods should use all of their parameters.
- // See comments below about why this isn't used.
-#pragma warning disable xUnit1026
- bool isPersistent,
-#pragma warning restore xUnit1026
- bool externalLogin)
+ public async Task CanResignIn(bool isPersistent, bool externalLogin)
{
// Setup
var user = new PocoUser { UserName = "Foo" };
var context = new DefaultHttpContext();
var auth = MockAuth(context);
var loginProvider = "loginprovider";
- var id = new ClaimsIdentity();
+ var id = new ClaimsIdentity("authscheme");
if (externalLogin)
{
id.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider));
}
- // REVIEW: auth changes we lost the ability to mock is persistent
- //var properties = new AuthenticationProperties { IsPersistent = isPersistent };
- var authResult = AuthenticateResult.NoResult();
+
+ var claimsPrincipal = new ClaimsPrincipal(id);
+ var properties = new AuthenticationProperties { IsPersistent = isPersistent };
+ var authResult = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, properties, "authscheme"));
auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
.Returns(Task.FromResult(authResult)).Verifiable();
var manager = SetupUserManager(user);
+ manager.Setup(m => m.GetUserId(claimsPrincipal)).Returns(user.Id.ToString());
var signInManager = new Mock>(manager.Object,
new HttpContextAccessor { HttpContext = context },
new Mock>().Object,
null, null, new Mock().Object, null)
{ CallBase = true };
- //signInManager.Setup(s => s.SignInAsync(user, It.Is(p => p.IsPersistent == isPersistent),
- //externalLogin? loginProvider : null)).Returns(Task.FromResult(0)).Verifiable();
- signInManager.Setup(s => s.SignInWithClaimsAsync(user, It.IsAny(), It.IsAny>())).Returns(Task.FromResult(0)).Verifiable();
+
+ signInManager.Setup(s => s.SignInWithClaimsAsync(user,
+ It.Is(properties => properties.IsPersistent == isPersistent),
+ It.Is>(claims => !externalLogin ||
+ claims.Any(claim => claim.Type == ClaimTypes.AuthenticationMethod && claim.Value == loginProvider))))
+ .Returns(Task.FromResult(0)).Verifiable();
+
signInManager.Object.Context = context;
// Act
@@ -634,6 +634,58 @@ public async Task CanResignIn(
signInManager.Verify();
}
+ [Fact]
+ public async Task ResignInNoOpsAndLogsErrorIfNotAuthenticated()
+ {
+ var user = new PocoUser { UserName = "Foo" };
+ var context = new DefaultHttpContext();
+ var auth = MockAuth(context);
+ var manager = SetupUserManager(user);
+ var logger = new TestLogger>();
+ var signInManager = new Mock>(manager.Object,
+ new HttpContextAccessor { HttpContext = context },
+ new Mock>().Object,
+ null, logger, new Mock().Object, null)
+ { CallBase = true };
+ auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
+ .Returns(Task.FromResult(AuthenticateResult.NoResult())).Verifiable();
+
+ await signInManager.Object.RefreshSignInAsync(user);
+
+ Assert.Contains("RefreshSignInAsync prevented because the user is not currently authenticated. Use SignInAsync instead for initial sign in.", logger.LogMessages);
+ auth.Verify();
+ signInManager.Verify(s => s.SignInWithClaimsAsync(It.IsAny(), It.IsAny(), It.IsAny>()),
+ Times.Never());
+ }
+
+ [Fact]
+ public async Task ResignInNoOpsAndLogsErrorIfAuthenticatedWithDifferentUser()
+ {
+ var user = new PocoUser { UserName = "Foo" };
+ var context = new DefaultHttpContext();
+ var auth = MockAuth(context);
+ var manager = SetupUserManager(user);
+ var logger = new TestLogger>();
+ var signInManager = new Mock>(manager.Object,
+ new HttpContextAccessor { HttpContext = context },
+ new Mock>().Object,
+ null, logger, new Mock().Object, null)
+ { CallBase = true };
+ var id = new ClaimsIdentity("authscheme");
+ var claimsPrincipal = new ClaimsPrincipal(id);
+ var authResult = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, new AuthenticationProperties(), "authscheme"));
+ auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
+ .Returns(Task.FromResult(authResult)).Verifiable();
+ manager.Setup(m => m.GetUserId(claimsPrincipal)).Returns("different");
+
+ await signInManager.Object.RefreshSignInAsync(user);
+
+ Assert.Contains("RefreshSignInAsync prevented because currently authenticated user has a different UserId. Use SignInAsync instead to change users.", logger.LogMessages);
+ auth.Verify();
+ signInManager.Verify(s => s.SignInWithClaimsAsync(It.IsAny(), It.IsAny(), It.IsAny>()),
+ Times.Never());
+ }
+
[Theory]
[InlineData(true, true, true, true)]
[InlineData(true, true, false, true)]
diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
index 9b26dbe5ad7d..f5f54fa1dc8b 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
@@ -217,6 +217,7 @@ public async Task UpdateDelegationRuleTest()
[ConditionalFact]
[DelegateSupportedCondition(true)]
+ [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/60141")]
public async Task DelegateAfterReceiverRestart()
{
var queueName = Guid.NewGuid().ToString();
diff --git a/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs b/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs
index b8af73a906dd..5cb38d2832c9 100644
--- a/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs
+++ b/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs
@@ -39,8 +39,9 @@ public KestrelServerImpl(
IEnumerable multiplexedFactories,
IHttpsConfigurationService httpsConfigurationService,
ILoggerFactory loggerFactory,
+ DiagnosticSource? diagnosticSource,
KestrelMetrics metrics)
- : this(transportFactories, multiplexedFactories, httpsConfigurationService, CreateServiceContext(options, loggerFactory, diagnosticSource: null, metrics))
+ : this(transportFactories, multiplexedFactories, httpsConfigurationService, CreateServiceContext(options, loggerFactory, diagnosticSource, metrics))
{
}
@@ -111,7 +112,8 @@ private static ServiceContext CreateServiceContext(IOptions ServiceContext.ServerOptions;
- private ServiceContext ServiceContext { get; }
+ // Internal for testing
+ internal ServiceContext ServiceContext { get; }
private KestrelTrace Trace => ServiceContext.Log;
diff --git a/src/Servers/Kestrel/Core/src/KestrelServer.cs b/src/Servers/Kestrel/Core/src/KestrelServer.cs
index 75cec0130767..7f2909c77cf6 100644
--- a/src/Servers/Kestrel/Core/src/KestrelServer.cs
+++ b/src/Servers/Kestrel/Core/src/KestrelServer.cs
@@ -36,6 +36,7 @@ public KestrelServer(IOptions options, IConnectionListener
Array.Empty(),
new SimpleHttpsConfigurationService(),
loggerFactory,
+ diagnosticSource: null,
new KestrelMetrics(new DummyMeterFactory()));
}
diff --git a/src/Servers/Kestrel/Core/test/KestrelServerTests.cs b/src/Servers/Kestrel/Core/test/KestrelServerTests.cs
index f3f4e3a60afd..6837ae0218de 100644
--- a/src/Servers/Kestrel/Core/test/KestrelServerTests.cs
+++ b/src/Servers/Kestrel/Core/test/KestrelServerTests.cs
@@ -308,6 +308,7 @@ private static KestrelServerImpl CreateKestrelServer(
multiplexedFactories,
httpsConfigurationService,
loggerFactory ?? new LoggerFactory(new[] { new KestrelTestLoggerProvider() }),
+ diagnosticSource: null,
metrics ?? new KestrelMetrics(new TestMeterFactory()));
}
diff --git a/src/Servers/Kestrel/Kestrel/test/WebHostBuilderKestrelExtensionsTests.cs b/src/Servers/Kestrel/Kestrel/test/WebHostBuilderKestrelExtensionsTests.cs
index 759d074a6d82..b24da893ab53 100644
--- a/src/Servers/Kestrel/Kestrel/test/WebHostBuilderKestrelExtensionsTests.cs
+++ b/src/Servers/Kestrel/Kestrel/test/WebHostBuilderKestrelExtensionsTests.cs
@@ -2,10 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections;
+using System.IO.Pipelines;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.Kestrel.Core;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
using Microsoft.Extensions.DependencyInjection;
@@ -107,6 +109,11 @@ public void ServerIsKestrelServerImpl()
.UseKestrel()
.Configure(app => { });
- Assert.IsType(hostBuilder.Build().Services.GetService());
+ var server = Assert.IsType(hostBuilder.Build().Services.GetService());
+
+ Assert.NotNull(server.ServiceContext.DiagnosticSource);
+ Assert.IsType(server.ServiceContext.Metrics);
+ Assert.Equal(PipeScheduler.ThreadPool, server.ServiceContext.Scheduler);
+ Assert.Equal(TimeProvider.System, server.ServiceContext.TimeProvider);
}
}
diff --git a/src/SignalR/clients/java/signalr/build.gradle b/src/SignalR/clients/java/signalr/build.gradle
index 895f8c4338d3..3e192445c97e 100644
--- a/src/SignalR/clients/java/signalr/build.gradle
+++ b/src/SignalR/clients/java/signalr/build.gradle
@@ -22,7 +22,7 @@ allprojects {
version project.findProperty('packageVersion') ?: "99.99.99-dev"
java {
- sourceCompatibility = 1.8
+ sourceCompatibility = 1.9
}
repositories {
diff --git a/src/SignalR/clients/java/signalr/test/signalr.client.java.Tests.javaproj b/src/SignalR/clients/java/signalr/test/signalr.client.java.Tests.javaproj
index 823c53ae8a72..8068629f03b3 100644
--- a/src/SignalR/clients/java/signalr/test/signalr.client.java.Tests.javaproj
+++ b/src/SignalR/clients/java/signalr/test/signalr.client.java.Tests.javaproj
@@ -6,6 +6,8 @@
true
true
+
+ OSX.15.Amd64.Open;$(SkipHelixQueues)
$(OutputPath)
true
diff --git a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/GsonHubProtocolTest.java b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/GsonHubProtocolTest.java
index 53454be031b6..d696a74850eb 100644
--- a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/GsonHubProtocolTest.java
+++ b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/GsonHubProtocolTest.java
@@ -444,7 +444,7 @@ public void invocationBindingFailureWhenParsingLocalDateTimeWithoutAppropriateTy
assertEquals(HubMessageType.INVOCATION_BINDING_FAILURE, message.getMessageType());
InvocationBindingFailureMessage failureMessage = (InvocationBindingFailureMessage) messages.get(0);
- assertEquals("java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 41 path $.arguments[0]", failureMessage.getException().getMessage());
+ assertEquals("com.google.gson.JsonSyntaxException", failureMessage.getException().getClass().getName());
}
@Test
diff --git a/src/submodules/googletest b/src/submodules/googletest
index 7d76a231b0e2..e235eb34c6c4 160000
--- a/src/submodules/googletest
+++ b/src/submodules/googletest
@@ -1 +1 @@
-Subproject commit 7d76a231b0e29caf86e68d1df858308cd53b2a66
+Subproject commit e235eb34c6c4fed790ccdad4b16394301360dcd4