diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 5dbf8980ea1637..968403269807c5 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,7 +15,7 @@
]
},
"microsoft.dotnet.xharness.cli": {
- "version": "8.0.0-prerelease.23523.1",
+ "version": "9.0.0-prerelease.23526.1",
"commands": [
"xharness"
]
diff --git a/eng/Subsets.props b/eng/Subsets.props
index f2480616431b51..ce90e8748f887d 100644
--- a/eng/Subsets.props
+++ b/eng/Subsets.props
@@ -336,7 +336,8 @@
$(CoreClrProjectRoot)tools\r2rdump\R2RDump.csproj;
$(CoreClrProjectRoot)tools\dotnet-pgo\dotnet-pgo.csproj;
$(CoreClrProjectRoot)tools\aot\ILCompiler\repro\repro.csproj;
- $(CoreClrProjectRoot)tools\r2rtest\R2RTest.csproj" Category="clr" Condition="'$(DotNetBuildFromSource)' != 'true'"/>
+ $(CoreClrProjectRoot)tools\r2rtest\R2RTest.csproj;
+ $(CoreClrProjectRoot)tools\AssemblyChecker\AssemblyChecker.csproj" Category="clr" Condition="'$(DotNetBuildFromSource)' != 'true'"/>
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index dc9cae22c8913a..ef03b5d42055f7 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -90,14 +90,14 @@
45dd3a73dd5b64b010c4251303b3664bb30df029
-
+
https://github.com/dotnet/emsdk
- cd13d57eccb71580227d612efc2fa27c5512aef4
+ 104f09072729ed5953f0be303f62e8567f3a5478
-
+
https://github.com/dotnet/source-build-reference-packages
- d3fbf3c3d4c4f142ea12efceaa6efece9ad2e6b5
+ 947ef94c52440c781aeb6ee13e95a9ec9992e444
@@ -107,83 +107,82 @@
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
- https://github.com/dotnet/xliff-tasks
- d66a09c8b11e1235273c8e6cd946e5c8e247f189
-
+
+ https://github.com/dotnet/arcade
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
https://github.com/dotnet/runtime-assets
@@ -293,62 +292,62 @@
https://github.com/dotnet/llvm-project
6f49d078f656896bfb9fdee6e76c2ef7b63dab45
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/runtime
- 2959e1acd09aec0f1e59db9cbe41f3701b0bd4dd
+ e5c631d28b985b773b28d0cb2346f49a92bd41dd
-
+
https://github.com/dotnet/xharness
- 3fc757d9b48e116713d1e0e3a3bd111a588905cb
+ ab9528860ac51bb0aa6112fa2605b18c926594ef
-
+
https://github.com/dotnet/xharness
- 3fc757d9b48e116713d1e0e3a3bd111a588905cb
+ ab9528860ac51bb0aa6112fa2605b18c926594ef
-
+
https://github.com/dotnet/xharness
- 3fc757d9b48e116713d1e0e3a3bd111a588905cb
+ ab9528860ac51bb0aa6112fa2605b18c926594ef
-
+
https://github.com/dotnet/arcade
- 6a5ca678aef84f34a1fccc46f76623f41da56553
+ bb2b4326ddf03d86c92bd125dba87e9d8df63463
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
https://github.com/dotnet/hotreload-utils
@@ -379,18 +378,18 @@
https://github.com/dotnet/roslyn-analyzers
b4ed6a3093cfd3c8d353214ce97aaa7d24cf2df1
-
+
https://github.com/dotnet/sdk
- 520797bdd9cf4ea016f28b14fa810aa295c931d6
+ d2c0ee3b304fd04ab9c0128c5a8347edb72aeb1f
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e5d9d61ccb43b9135a7471429b338aa7332e2eb5
+ d80a861521d84459c9290c31127b2a0ce511f279
@@ -398,9 +397,9 @@
https://github.com/NuGet/NuGet.Client
8fef55f5a55a3b4f2c96cd1a9b5ddc51d4b927f8
-
+
https://github.com/dotnet/installer
- 62a1b533e387db43c0e9b1b01754e040a143f96a
+ f3c39098a298693206acf00c470530407c8b2ba8
diff --git a/eng/Versions.props b/eng/Versions.props
index 0e554925a88b10..421ed7583c8617 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -80,31 +80,31 @@
0.2.0
- 9.0.100-alpha.1.23524.12
+ 9.0.100-alpha.1.23530.1
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 2.5.1-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
- 9.0.0-beta.23518.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 2.5.3-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
+ 9.0.0-beta.23528.2
6.0.0-preview.1.102
- 9.0.0-alpha.1.23523.1
+ 9.0.0-alpha.1.23529.4
6.0.0
- 9.0.0-alpha.1.23523.1
+ 9.0.0-alpha.1.23529.4
16.0.5-alpha.1.23517.4
16.0.5-alpha.1.23517.4
16.0.5-alpha.1.23517.4
@@ -131,12 +131,12 @@
5.0.0
5.0.0
7.0.0
- 9.0.0-alpha.1.23523.1
+ 9.0.0-alpha.1.23529.4
6.0.0
7.0.0
4.5.4
4.5.0
- 9.0.0-alpha.1.23523.1
+ 9.0.0-alpha.1.23529.4
8.0.0-beta.23516.1
8.0.0-beta.23516.1
@@ -153,12 +153,12 @@
8.0.0-beta.23516.1
8.0.0-beta.23516.1
- 1.0.0-prerelease.23521.3
- 1.0.0-prerelease.23521.3
- 1.0.0-prerelease.23521.3
- 1.0.0-prerelease.23521.3
- 1.0.0-prerelease.23521.3
- 1.0.0-prerelease.23521.3
+ 1.0.0-prerelease.23525.5
+ 1.0.0-prerelease.23525.5
+ 1.0.0-prerelease.23525.5
+ 1.0.0-prerelease.23525.5
+ 1.0.0-prerelease.23525.5
+ 1.0.0-prerelease.23525.5
16.11.27-beta1.23180.1
2.0.0-beta4.23307.1
@@ -178,9 +178,9 @@
1.1.0
17.4.0-preview-20220707-01
- 8.0.0-prerelease.23523.1
- 8.0.0-prerelease.23523.1
- 8.0.0-prerelease.23523.1
+ 9.0.0-prerelease.23526.1
+ 9.0.0-prerelease.23526.1
+ 9.0.0-prerelease.23526.1
9.0.0-alpha.0.23523.3
3.12.0
4.1.0
@@ -205,7 +205,7 @@
0.11.4-alpha.23509.2
- 9.0.0-alpha.1.23523.1
+ 9.0.0-alpha.1.23529.4
9.0.0-alpha.1.23523.1
@@ -230,7 +230,7 @@
Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml
like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-9_0_100_Transport
-->
- 9.0.0-alpha.1.23523.3
+ 9.0.0-alpha.1.23528.4
$(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion)
1.1.87-gba258badda
@@ -248,7 +248,7 @@
3.1.7
1.0.406601
- 9.0.100-alpha.1.23525.7
+ 9.0.100-alpha.1.23529.1
$(MicrosoftDotnetSdkInternalVersion)
diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index cb0aaa76063453..00288a300653a0 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -40,7 +40,7 @@ if(TARGET_ARCH_NAME STREQUAL "arm")
set(TOOLCHAIN "arm-linux-gnueabihf")
endif()
if(TIZEN)
- set(TIZEN_TOOLCHAIN "armv7hl-tizen-linux-gnueabihf/13.1.0")
+ set(TIZEN_TOOLCHAIN "armv7hl-tizen-linux-gnueabihf/9.2.0")
endif()
elseif(TARGET_ARCH_NAME STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR aarch64)
@@ -49,7 +49,7 @@ elseif(TARGET_ARCH_NAME STREQUAL "arm64")
elseif(LINUX)
set(TOOLCHAIN "aarch64-linux-gnu")
if(TIZEN)
- set(TIZEN_TOOLCHAIN "aarch64-tizen-linux-gnu/13.1.0")
+ set(TIZEN_TOOLCHAIN "aarch64-tizen-linux-gnu/9.2.0")
endif()
elseif(FREEBSD)
set(triple "aarch64-unknown-freebsd12")
@@ -98,7 +98,7 @@ elseif(TARGET_ARCH_NAME STREQUAL "x64")
elseif(LINUX)
set(TOOLCHAIN "x86_64-linux-gnu")
if(TIZEN)
- set(TIZEN_TOOLCHAIN "x86_64-tizen-linux-gnu/13.1.0")
+ set(TIZEN_TOOLCHAIN "x86_64-tizen-linux-gnu/9.2.0")
endif()
elseif(FREEBSD)
set(triple "x86_64-unknown-freebsd12")
@@ -115,7 +115,7 @@ elseif(TARGET_ARCH_NAME STREQUAL "x86")
set(TOOLCHAIN "i686-linux-gnu")
endif()
if(TIZEN)
- set(TIZEN_TOOLCHAIN "i586-tizen-linux-gnu/13.1.0")
+ set(TIZEN_TOOLCHAIN "i586-tizen-linux-gnu/9.2.0")
endif()
else()
message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm, arm64, armel, armv6, ppc64le, riscv64, s390x, x64 and x86 are supported!")
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index fdd0cbb91f8596..e8def7e6a85f21 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -158,7 +158,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) {
$env:DOTNET_MULTILEVEL_LOOKUP=0
# Disable first run since we do not need all ASP.NET packages restored.
- $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+ $env:DOTNET_NOLOGO=1
# Disable telemetry on CI.
if ($ci) {
@@ -228,7 +228,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) {
Write-PipelinePrependPath -Path $dotnetRoot
Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0'
- Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1'
+ Write-PipelineSetVariable -Name 'DOTNET_NOLOGO' -Value '1'
return $global:_DotNetInstallDir = $dotnetRoot
}
diff --git a/eng/common/tools.sh b/eng/common/tools.sh
index e8d478943341df..710e64df967fd7 100755
--- a/eng/common/tools.sh
+++ b/eng/common/tools.sh
@@ -112,7 +112,7 @@ function InitializeDotNetCli {
export DOTNET_MULTILEVEL_LOOKUP=0
# Disable first run since we want to control all package sources
- export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+ export DOTNET_NOLOGO=1
# Disable telemetry on CI
if [[ $ci == true ]]; then
@@ -165,7 +165,7 @@ function InitializeDotNetCli {
Write-PipelinePrependPath -path "$dotnet_root"
Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0"
- Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1"
+ Write-PipelineSetVariable -name "DOTNET_NOLOGO" -value "1"
# return value
_InitializeDotNetCli="$dotnet_root"
diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml
index ac43f54499e9b1..bd84175767331e 100644
--- a/eng/pipelines/common/evaluate-default-paths.yml
+++ b/eng/pipelines/common/evaluate-default-paths.yml
@@ -226,6 +226,7 @@ jobs:
- src/mono/wasm/host/*
- src/mono/wasm/runtime/*
- src/mono/wasm/templates/*
+ - src/mono/wasm/testassets/*
- src/mono/wasm/Wasm.Build.Tests/*
- ${{ parameters._const_paths._wasm_chrome }}
- ${{ parameters._const_paths._wasm_src_native }}
@@ -266,6 +267,7 @@ jobs:
- src/mono/wasi/*
- src/mono/wasm/debugger/*
- src/mono/wasm/host/*
+ - src/mono/wasm/testassets/*
- src/mono/wasm/Wasm.Build.Tests/*
- ${{ parameters._const_paths._wasm_pipelines }}
- ${{ parameters._const_paths._always_exclude }}
@@ -285,6 +287,7 @@ jobs:
- src/mono/mono/component/mini-wasm-debugger.c
- src/mono/wasm/debugger/*
- src/mono/wasm/host/*
+ - src/mono/wasm/testassets/*
- src/mono/wasm/Wasm.Build.Tests/*
- src/mono/nuget/Microsoft.NET.Runtime*
src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/*
diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml
index c641821da3855a..0efe765230720f 100644
--- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml
+++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml
@@ -112,14 +112,14 @@ jobs:
- browser_wasm
#- browser_wasm_win
nameSuffix: _Threading
- extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
+ extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }}
isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }}
# Always run for runtime-wasm because tests are not run in runtime
alwaysRun: ${{ parameters.isWasmOnlyBuild }}
- # NOTE - Since threading is experimental, we don't want to block mainline work
- shouldContinueOnError: true
+ # NOTE - Since threading is experimental, we don't want to block mainline work
+ # TODO put back shouldContinueOnError: true
scenarios:
- WasmTestOnBrowser
#- WasmTestOnNodeJS - this is not supported yet, https://github.com/dotnet/runtime/issues/85592
@@ -198,7 +198,7 @@ jobs:
- browser_wasm
- browser_wasm_win
nameSuffix: MultiThreaded
- extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
+ extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
condition: ne(variables['wasmMultiThreadedBuildOnlyNeededOnDefaultPipeline'], true)
publishArtifactsForWorkload: true
publishWBT: false
diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml
index 4a50ed665e24ee..b30b8889f286a7 100644
--- a/eng/pipelines/mono/templates/workloads-build.yml
+++ b/eng/pipelines/mono/templates/workloads-build.yml
@@ -65,6 +65,7 @@ jobs:
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.Current.Manifest*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest*.nupkg
+ IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net8.Manifest*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg
diff --git a/eng/pipelines/runtime-wasm-perf.yml b/eng/pipelines/runtime-wasm-perf.yml
index 120cc2df85307d..478bbb81f8a4c8 100644
--- a/eng/pipelines/runtime-wasm-perf.yml
+++ b/eng/pipelines/runtime-wasm-perf.yml
@@ -39,7 +39,7 @@ extends:
runProfile: 'v8'
collectHelixLogsScript: ${{ variables._wasmCollectHelixLogsScript }}
onlySanityCheck: true
- #perfForkToUse:
+ #perfForkToUse: - dummy change
#url: https://github.com/radical/performance
#branch: fix-build
#downloadSpecificBuild:
diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml
index fc8b0ad617ebc1..d06566403f3ed1 100644
--- a/eng/pipelines/runtime.yml
+++ b/eng/pipelines/runtime.yml
@@ -566,7 +566,7 @@ extends:
- browser_wasm_win
condition: or(eq(variables.isRollingBuild, true), eq(variables.wasmSingleThreadedBuildOnlyNeededOnDefaultPipeline, true))
nameSuffix: MultiThreaded
- extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
+ extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
publishArtifactsForWorkload: true
publishWBT: false
@@ -602,7 +602,7 @@ extends:
platforms:
- browser_wasm
nameSuffix: _Threading_Smoke
- extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
+ extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
shouldRunSmokeOnly: true
alwaysRun: ${{ variables.isRollingBuild }}
scenarios:
diff --git a/eng/testing/workloads-testing.targets b/eng/testing/workloads-testing.targets
index eb8a84468d9dc0..d205af6fbdfde7 100644
--- a/eng/testing/workloads-testing.targets
+++ b/eng/testing/workloads-testing.targets
@@ -28,6 +28,27 @@
+
+ <_DotNetInstallScriptName Condition="!$([MSBuild]::IsOSPlatform('windows'))">dotnet-install.sh
+ <_DotNetInstallScriptName Condition=" $([MSBuild]::IsOSPlatform('windows'))">dotnet-install.ps1
+
+ <_DotNetInstallScriptPath>$(ArtifactsObjDir)$(_DotNetInstallScriptName)
+
+
+
+ <_DotNetInstallCommand Condition="!$([MSBuild]::IsOSPlatform('windows'))"
+ >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v $(SdkVersionForWorkloadTesting)
+ <_DotNetInstallCommand Condition="$([MSBuild]::IsOSPlatform('windows'))"
+ >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Version $(SdkVersionForWorkloadTesting)
+
+
+
+ <_DotNetInstallCommand Condition="!$([MSBuild]::IsOSPlatform('windows'))"
+ >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v latest -q daily --channel 9.0
+ <_DotNetInstallCommand Condition="$([MSBuild]::IsOSPlatform('windows'))"
+ >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Quality daily -Channel 9.0
+
+
$(NoWarn);AD0001
+
+ true
@@ -144,7 +146,6 @@
-
@@ -231,10 +232,9 @@
-
+
-
@@ -257,8 +257,8 @@
-
- System\Runtime\InteropServices\Variant.cs
+
+ System\Runtime\InteropServices\BuiltInVariantExtensions.cs
Interop\Windows\Kernel32\Interop.IsDebuggerPresent.cs
@@ -305,9 +305,6 @@
Interop\Unix\System.Native\Interop.Exit.cs
-
- Interop\Unix\System.Native\Interop.Threading.cs
-
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
deleted file mode 100644
index 2d1afc04d5b730..00000000000000
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Reflection.Emit
-{
- public sealed class LocalBuilder : LocalVariableInfo
- {
- internal LocalBuilder()
- {
- // Prevent generating a default constructor
- }
-
- public override bool IsPinned
- {
- get
- {
- return default;
- }
- }
-
- public override int LocalIndex
- {
- get
- {
- return default;
- }
- }
-
- public override Type LocalType
- {
- get
- {
- return default;
- }
- }
- }
-}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
index 8093c0f71ff147..7e8293e1a1653f 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
@@ -111,7 +111,7 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte
cctors[cctorIndex].HoldingThread = ManagedThreadIdNone;
NoisyLog("Releasing cctor lock, context={0}, thread={1}", pContext, currentManagedThreadId);
- cctorLock.Release();
+ cctorLock.Exit();
}
}
else
@@ -142,10 +142,10 @@ private static unsafe bool DeadlockAwareAcquire(CctorHandle cctor, StaticClassCo
int cctorIndex = cctor.Index;
Cctor[] cctors = cctor.Array;
Lock lck = cctors[cctorIndex].Lock;
- if (lck.IsAcquired)
+ if (lck.IsHeldByCurrentThread)
return false; // Thread recursively triggered the same cctor.
- if (lck.TryAcquire(waitIntervalInMS))
+ if (lck.TryEnter(waitIntervalInMS))
return true;
// We couldn't acquire the lock. See if this .cctor is involved in a cross-thread deadlock. If so, break
@@ -164,7 +164,7 @@ private static unsafe bool DeadlockAwareAcquire(CctorHandle cctor, StaticClassCo
// deadlock themselves, then that's a bug in user code.
for (;;)
{
- using (LockHolder.Hold(s_cctorGlobalLock))
+ using (s_cctorGlobalLock.EnterScope())
{
// Ask the guy who holds the cctor lock we're trying to acquire who he's waiting for. Keep
// walking down that chain until we either discover a cycle or reach a non-blocking state. Note
@@ -233,7 +233,7 @@ private static unsafe bool DeadlockAwareAcquire(CctorHandle cctor, StaticClassCo
waitIntervalInMS *= 2;
// We didn't find a cycle yet, try to take the lock again.
- if (lck.TryAcquire(waitIntervalInMS))
+ if (lck.TryEnter(waitIntervalInMS))
return true;
} // infinite loop
}
@@ -283,7 +283,7 @@ public static CctorHandle GetCctor(StaticClassConstructionContext* pContext)
}
#endif // TARGET_WASM
- using (LockHolder.Hold(s_cctorGlobalLock))
+ using (s_cctorGlobalLock.EnterScope())
{
Cctor[]? resultArray = null;
int resultIndex = -1;
@@ -355,14 +355,14 @@ public static int Count
{
get
{
- Debug.Assert(s_cctorGlobalLock.IsAcquired);
+ Debug.Assert(s_cctorGlobalLock.IsHeldByCurrentThread);
return s_count;
}
}
public static void Release(CctorHandle cctor)
{
- using (LockHolder.Hold(s_cctorGlobalLock))
+ using (s_cctorGlobalLock.EnterScope())
{
Cctor[] cctors = cctor.Array;
int cctorIndex = cctor.Index;
@@ -419,7 +419,7 @@ public static int MarkThreadAsBlocked(int managedThreadId, CctorHandle blockedOn
#else
const int Grow = 10;
#endif
- using (LockHolder.Hold(s_cctorGlobalLock))
+ using (s_cctorGlobalLock.EnterScope())
{
s_blockingRecords ??= new BlockingRecord[Grow];
int found;
@@ -450,14 +450,14 @@ public static int MarkThreadAsBlocked(int managedThreadId, CctorHandle blockedOn
public static void UnmarkThreadAsBlocked(int blockRecordIndex)
{
// This method must never throw
- s_cctorGlobalLock.Acquire();
+ s_cctorGlobalLock.Enter();
s_blockingRecords[blockRecordIndex].BlockedOn = new CctorHandle(null, 0);
- s_cctorGlobalLock.Release();
+ s_cctorGlobalLock.Exit();
}
public static CctorHandle GetCctorThatThreadIsBlockedOn(int managedThreadId)
{
- Debug.Assert(s_cctorGlobalLock.IsAcquired);
+ Debug.Assert(s_cctorGlobalLock.IsHeldByCurrentThread);
for (int i = 0; i < s_nextBlockingRecordIndex; i++)
{
if (s_blockingRecords[i].ManagedThreadId == managedThreadId)
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs
index e776860562ca49..0fc6330a1c88e4 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs
@@ -951,7 +951,7 @@ private unsafe bool TryGetOrCreateObjectForComInstanceInternal(
if (!flags.HasFlag(CreateObjectFlags.UniqueInstance))
{
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
if (_rcwCache.TryGetValue(identity, out GCHandle handle))
{
@@ -1047,7 +1047,7 @@ private unsafe bool TryGetOrCreateObjectForComInstanceInternal(
return true;
}
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
object? cachedWrapper = null;
if (_rcwCache.TryGetValue(identity, out var existingHandle))
@@ -1092,7 +1092,7 @@ private unsafe bool TryGetOrCreateObjectForComInstanceInternal(
private void RemoveRCWFromCache(IntPtr comPointer, GCHandle expectedValue)
{
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
// TryGetOrCreateObjectForComInstanceInternal may have put a new entry into the cache
// in the time between the GC cleared the contents of the GC handle but before the
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs
index 18828c7ad17f78..97694ca5d66756 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs
@@ -5,6 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.InteropServices.ComTypes;
+using System.Runtime.InteropServices.Marshalling;
using System.Runtime.Versioning;
namespace System.Runtime.InteropServices
@@ -121,10 +122,10 @@ public static unsafe void GetNativeVariantForObject(object? obj, IntPtr pDstNati
{
ArgumentNullException.ThrowIfNull(pDstNativeVariant);
- Variant* data = (Variant*)pDstNativeVariant;
+ ComVariant* data = (ComVariant*)pDstNativeVariant;
if (obj == null)
{
- data->VariantType = VarEnum.VT_EMPTY;
+ *data = default;
return;
}
@@ -132,132 +133,132 @@ public static unsafe void GetNativeVariantForObject(object? obj, IntPtr pDstNati
{
// Int and String most used types.
case int value:
- data->AsI4 = value;
+ *data = ComVariant.Create(value);
break;
case string value:
- data->AsBstr = value;
+ *data = ComVariant.Create(new BStrWrapper(value));
break;
case bool value:
- data->AsBool = value;
+ *data = ComVariant.Create(value);
break;
case byte value:
- data->AsUi1 = value;
+ *data = ComVariant.Create(value);
break;
case sbyte value:
- data->AsI1 = value;
+ *data = ComVariant.Create(value);
break;
case short value:
- data->AsI2 = value;
+ *data = ComVariant.Create(value);
break;
case ushort value:
- data->AsUi2 = value;
+ *data = ComVariant.Create(value);
break;
case uint value:
- data->AsUi4 = value;
+ *data = ComVariant.Create(value);
break;
case long value:
- data->AsI8 = value;
+ *data = ComVariant.Create(value);
break;
case ulong value:
- data->AsUi8 = value;
+ *data = ComVariant.Create(value);
break;
case float value:
- data->AsR4 = value;
+ *data = ComVariant.Create(value);
break;
case double value:
- data->AsR8 = value;
+ *data = ComVariant.Create(value);
break;
case DateTime value:
- data->AsDate = value;
+ *data = ComVariant.Create(value);
break;
case decimal value:
- data->AsDecimal = value;
+ *data = ComVariant.Create(value);
break;
case char value:
- data->AsUi2 = value;
+ *data = ComVariant.Create(value);
break;
case BStrWrapper value:
- data->AsBstr = value.WrappedObject;
+ *data = ComVariant.Create(value);
break;
#pragma warning disable 0618 // CurrencyWrapper is obsolete
case CurrencyWrapper value:
- data->AsCy = value.WrappedObject;
+ *data = ComVariant.Create(value);
break;
#pragma warning restore 0618
case UnknownWrapper value:
- data->AsUnknown = value.WrappedObject;
+ *data = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, GetIUnknownForObject(value.WrappedObject));
break;
case DispatchWrapper value:
- data->AsDispatch = value.WrappedObject;
+ *data = ComVariant.CreateRaw(VarEnum.VT_DISPATCH, GetIDispatchForObject(value.WrappedObject));
break;
case ErrorWrapper value:
- data->AsError = value.ErrorCode;
+ *data = ComVariant.Create(value);
break;
case VariantWrapper value:
throw new ArgumentException();
case DBNull value:
- data->SetAsNULL();
+ *data = ComVariant.Null;
break;
case Missing value:
- data->AsError = DISP_E_PARAMNOTFOUND;
+ *data = ComVariant.CreateRaw(VarEnum.VT_ERROR, DISP_E_PARAMNOTFOUND);
break;
case IConvertible value:
switch (value.GetTypeCode())
{
case TypeCode.Empty:
- data->VariantType = VarEnum.VT_EMPTY;
+ *data = default;
break;
case TypeCode.Object:
- data->AsUnknown = value;
+ *data = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, GetIUnknownForObject(value));
break;
case TypeCode.DBNull:
- data->SetAsNULL();
+ *data = ComVariant.Null;
break;
case TypeCode.Boolean:
- data->AsBool = value.ToBoolean(null);
+ *data = ComVariant.Create(value.ToBoolean(null));
break;
case TypeCode.Char:
- data->AsUi2 = value.ToChar(null);
+ *data = ComVariant.Create(value.ToChar(null));
break;
case TypeCode.SByte:
- data->AsI1 = value.ToSByte(null);
+ *data = ComVariant.Create(value.ToSByte(null));
break;
case TypeCode.Byte:
- data->AsUi1 = value.ToByte(null);
+ *data = ComVariant.Create(value.ToByte(null));
break;
case TypeCode.Int16:
- data->AsI2 = value.ToInt16(null);
+ *data = ComVariant.Create(value.ToInt16(null));
break;
case TypeCode.UInt16:
- data->AsUi2 = value.ToUInt16(null);
+ *data = ComVariant.Create(value.ToUInt16(null));
break;
case TypeCode.Int32:
- data->AsI4 = value.ToInt32(null);
+ *data = ComVariant.Create(value.ToInt32(null));
break;
case TypeCode.UInt32:
- data->AsUi4 = value.ToUInt32(null);
+ *data = ComVariant.Create(value.ToUInt32(null));
break;
case TypeCode.Int64:
- data->AsI8 = value.ToInt64(null);
+ *data = ComVariant.Create(value.ToInt64(null));
break;
case TypeCode.UInt64:
- data->AsUi8 = value.ToUInt64(null);
+ *data = ComVariant.Create(value.ToUInt64(null));
break;
case TypeCode.Single:
- data->AsR4 = value.ToSingle(null);
+ *data = ComVariant.Create(value.ToSingle(null));
break;
case TypeCode.Double:
- data->AsR8 = value.ToDouble(null);
+ *data = ComVariant.Create(value.ToDouble(null));
break;
case TypeCode.Decimal:
- data->AsDecimal = value.ToDecimal(null);
+ *data = ComVariant.Create(value.ToDecimal(null));
break;
case TypeCode.DateTime:
- data->AsDate = value.ToDateTime(null);
+ *data = ComVariant.Create(value.ToDateTime(null));
break;
case TypeCode.String:
- data->AsBstr = value.ToString();
+ *data = ComVariant.Create(new BStrWrapper(value.ToString(null)));
break;
default:
throw new NotSupportedException();
@@ -273,7 +274,7 @@ public static unsafe void GetNativeVariantForObject(object? obj, IntPtr pDstNati
case ValueType:
throw new NotSupportedException("VT_RECORD");
default:
- data->AsDispatch = obj;
+ *data = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, GetIDispatchForObject(obj));
break;
}
}
@@ -303,38 +304,35 @@ public static object GetObjectForIUnknown(IntPtr pUnk)
{
ArgumentNullException.ThrowIfNull(pSrcNativeVariant);
- Variant* data = (Variant*)pSrcNativeVariant;
+ ComVariant* data = (ComVariant*)pSrcNativeVariant;
- if (data->IsEmpty)
- {
- return null;
- }
-
- switch (data->VariantType)
+ switch (data->VarType)
{
+ case VarEnum.VT_EMPTY:
+ return null;
case VarEnum.VT_NULL:
return DBNull.Value;
- case VarEnum.VT_I1: return data->AsI1;
- case VarEnum.VT_I2: return data->AsI2;
- case VarEnum.VT_I4: return data->AsI4;
- case VarEnum.VT_I8: return data->AsI8;
- case VarEnum.VT_UI1: return data->AsUi1;
- case VarEnum.VT_UI2: return data->AsUi2;
- case VarEnum.VT_UI4: return data->AsUi4;
- case VarEnum.VT_UI8: return data->AsUi8;
- case VarEnum.VT_INT: return data->AsInt;
- case VarEnum.VT_UINT: return data->AsUint;
- case VarEnum.VT_BOOL: return data->AsBool;
- case VarEnum.VT_ERROR: return data->AsError;
- case VarEnum.VT_R4: return data->AsR4;
- case VarEnum.VT_R8: return data->AsR8;
- case VarEnum.VT_DECIMAL: return data->AsDecimal;
- case VarEnum.VT_CY: return data->AsCy;
- case VarEnum.VT_DATE: return data->AsDate;
- case VarEnum.VT_BSTR: return data->AsBstr;
- case VarEnum.VT_UNKNOWN: return data->AsUnknown;
- case VarEnum.VT_DISPATCH: return data->AsDispatch;
+ case VarEnum.VT_I1: return data->As();
+ case VarEnum.VT_I2: return data->As();
+ case VarEnum.VT_I4: return data->As();
+ case VarEnum.VT_I8: return data->As();
+ case VarEnum.VT_UI1: return data->As();
+ case VarEnum.VT_UI2: return data->As();
+ case VarEnum.VT_UI4: return data->As();
+ case VarEnum.VT_UI8: return data->As();
+ case VarEnum.VT_INT: return data->As();
+ case VarEnum.VT_UINT: return data->As();
+ case VarEnum.VT_BOOL: return data->As() != -1;
+ case VarEnum.VT_ERROR: return data->As();
+ case VarEnum.VT_R4: return data->As();
+ case VarEnum.VT_R8: return data->As();
+ case VarEnum.VT_DECIMAL: return data->As();
+ case VarEnum.VT_CY: return decimal.FromOACurrency(data->GetRawDataRef());
+ case VarEnum.VT_DATE: return data->As();
+ case VarEnum.VT_BSTR: return PtrToStringBSTR(data->GetRawDataRef());
+ case VarEnum.VT_UNKNOWN: return GetObjectForIUnknown(data->GetRawDataRef());
+ case VarEnum.VT_DISPATCH: return GetObjectForIUnknown(data->GetRawDataRef());
default:
// Other VARIANT types not supported yet.
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs
index a567debf03708e..c8fdbb60384348 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs
@@ -56,7 +56,7 @@ private unsafe void AssertIsNotInList(Waiter waiter)
private unsafe void AddWaiter(Waiter waiter)
{
- Debug.Assert(_lock.IsAcquired);
+ Debug.Assert(_lock.IsHeldByCurrentThread);
AssertIsNotInList(waiter);
waiter.prev = _waitersTail;
@@ -70,7 +70,7 @@ private unsafe void AddWaiter(Waiter waiter)
private unsafe void RemoveWaiter(Waiter waiter)
{
- Debug.Assert(_lock.IsAcquired);
+ Debug.Assert(_lock.IsHeldByCurrentThread);
AssertIsInList(waiter);
if (waiter.next != null)
@@ -101,13 +101,13 @@ public unsafe bool Wait(int millisecondsTimeout)
{
ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1);
- if (!_lock.IsAcquired)
+ if (!_lock.IsHeldByCurrentThread)
throw new SynchronizationLockException();
Waiter waiter = GetWaiterForCurrentThread();
AddWaiter(waiter);
- uint recursionCount = _lock.ReleaseAll();
+ uint recursionCount = _lock.ExitAll();
bool success = false;
try
{
@@ -115,8 +115,8 @@ public unsafe bool Wait(int millisecondsTimeout)
}
finally
{
- _lock.Reacquire(recursionCount);
- Debug.Assert(_lock.IsAcquired);
+ _lock.Reenter(recursionCount);
+ Debug.Assert(_lock.IsHeldByCurrentThread);
if (!waiter.signalled)
{
@@ -140,7 +140,7 @@ public unsafe bool Wait(int millisecondsTimeout)
public unsafe void SignalAll()
{
- if (!_lock.IsAcquired)
+ if (!_lock.IsHeldByCurrentThread)
throw new SynchronizationLockException();
while (_waitersHead != null)
@@ -149,7 +149,7 @@ public unsafe void SignalAll()
public unsafe void SignalOne()
{
- if (!_lock.IsAcquired)
+ if (!_lock.IsHeldByCurrentThread)
throw new SynchronizationLockException();
Waiter? waiter = _waitersHead;
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs
index f8a5e61ecbb65c..a81051a58ba17e 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs
@@ -24,8 +24,8 @@ public static long CompareExchange(ref long location1, long value, long comparan
}
[Intrinsic]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: NotNullIfNotNull(nameof(location1))]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T CompareExchange(ref T location1, T value, T comparand) where T : class?
{
return Unsafe.As(RuntimeImports.InterlockedCompareExchange(ref Unsafe.As(ref location1), value, comparand));
@@ -69,8 +69,8 @@ public static long Exchange(ref long location1, long value)
}
[Intrinsic]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: NotNullIfNotNull(nameof(location1))]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class?
{
return Unsafe.As(RuntimeImports.InterlockedExchange(ref Unsafe.As(ref location1), value));
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs
new file mode 100644
index 00000000000000..690014f91691fa
--- /dev/null
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs
@@ -0,0 +1,229 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Diagnostics.Tracing;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+ public sealed partial class Lock
+ {
+ private const short SpinCountNotInitialized = short.MinValue;
+
+ // NOTE: Lock must not have a static (class) constructor, as Lock itself is used to synchronize
+ // class construction. If Lock has its own class constructor, this can lead to infinite recursion.
+ // All static data in Lock must be lazy-initialized.
+ private static int s_staticsInitializationStage;
+ private static bool s_isSingleProcessor;
+ private static short s_maxSpinCount;
+ private static short s_minSpinCount;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Lock() => _spinCount = SpinCountNotInitialized;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal bool TryEnterOneShot(int currentManagedThreadId)
+ {
+ Debug.Assert(currentManagedThreadId != 0);
+
+ if (State.TryLock(this))
+ {
+ Debug.Assert(_owningThreadId == 0);
+ Debug.Assert(_recursionCount == 0);
+ _owningThreadId = (uint)currentManagedThreadId;
+ return true;
+ }
+
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void Exit(int currentManagedThreadId)
+ {
+ Debug.Assert(currentManagedThreadId != 0);
+
+ if (_owningThreadId != (uint)currentManagedThreadId)
+ {
+ ThrowHelper.ThrowSynchronizationLockException_LockExit();
+ }
+
+ ExitImpl();
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) =>
+ TryEnterSlow(timeoutMs, currentThreadId, this);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal bool TryEnterSlow(int timeoutMs, int currentManagedThreadId, object associatedObject) =>
+ TryEnterSlow(timeoutMs, new ThreadId((uint)currentManagedThreadId), associatedObject).IsInitialized;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal bool GetIsHeldByCurrentThread(int currentManagedThreadId)
+ {
+ Debug.Assert(currentManagedThreadId != 0);
+
+ bool isHeld = _owningThreadId == (uint)currentManagedThreadId;
+ Debug.Assert(!isHeld || new State(this).IsLocked);
+ return isHeld;
+ }
+
+ internal uint ExitAll()
+ {
+ Debug.Assert(IsHeldByCurrentThread);
+
+ uint recursionCount = _recursionCount;
+ _owningThreadId = 0;
+ _recursionCount = 0;
+
+ State state = State.Unlock(this);
+ if (state.HasAnyWaiters)
+ {
+ SignalWaiterIfNecessary(state);
+ }
+
+ return recursionCount;
+ }
+
+ internal void Reenter(uint previousRecursionCount)
+ {
+ Debug.Assert(!IsHeldByCurrentThread);
+
+ Enter();
+ _recursionCount = previousRecursionCount;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private TryLockResult LazyInitializeOrEnter()
+ {
+ StaticsInitializationStage stage = (StaticsInitializationStage)Volatile.Read(ref s_staticsInitializationStage);
+ switch (stage)
+ {
+ case StaticsInitializationStage.Complete:
+ if (_spinCount == SpinCountNotInitialized)
+ {
+ _spinCount = s_maxSpinCount;
+ }
+ return TryLockResult.Spin;
+
+ case StaticsInitializationStage.Started:
+ // Spin-wait until initialization is complete or the lock is acquired to prevent class construction cycles
+ // later during a full wait
+ bool sleep = true;
+ while (true)
+ {
+ if (sleep)
+ {
+ Thread.UninterruptibleSleep0();
+ }
+ else
+ {
+ Thread.SpinWait(1);
+ }
+
+ stage = (StaticsInitializationStage)Volatile.Read(ref s_staticsInitializationStage);
+ if (stage == StaticsInitializationStage.Complete)
+ {
+ goto case StaticsInitializationStage.Complete;
+ }
+ else if (stage == StaticsInitializationStage.NotStarted)
+ {
+ goto default;
+ }
+
+ if (State.TryLock(this))
+ {
+ return TryLockResult.Locked;
+ }
+
+ sleep = !sleep;
+ }
+
+ default:
+ Debug.Assert(stage == StaticsInitializationStage.NotStarted);
+ if (TryInitializeStatics())
+ {
+ goto case StaticsInitializationStage.Complete;
+ }
+ goto case StaticsInitializationStage.Started;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool TryInitializeStatics()
+ {
+ // Since Lock is used to synchronize class construction, and some of the statics initialization may involve class
+ // construction, update the stage first to avoid infinite recursion
+ switch (
+ (StaticsInitializationStage)
+ Interlocked.CompareExchange(
+ ref s_staticsInitializationStage,
+ (int)StaticsInitializationStage.Started,
+ (int)StaticsInitializationStage.NotStarted))
+ {
+ case StaticsInitializationStage.Started:
+ return false;
+ case StaticsInitializationStage.Complete:
+ return true;
+ }
+
+ try
+ {
+ s_isSingleProcessor = Environment.IsSingleProcessor;
+ s_maxSpinCount = DetermineMaxSpinCount();
+ s_minSpinCount = DetermineMinSpinCount();
+
+ // Also initialize some types that are used later to prevent potential class construction cycles
+ NativeRuntimeEventSource.Log.IsEnabled();
+ }
+ catch
+ {
+ s_staticsInitializationStage = (int)StaticsInitializationStage.NotStarted;
+ throw;
+ }
+
+ Volatile.Write(ref s_staticsInitializationStage, (int)StaticsInitializationStage.Complete);
+ return true;
+ }
+
+ // Returns false until the static variable is lazy-initialized
+ internal static bool IsSingleProcessor => s_isSingleProcessor;
+
+ // Used to transfer the state when inflating thin locks
+ internal void InitializeLocked(int managedThreadId, uint recursionCount)
+ {
+ Debug.Assert(recursionCount == 0 || managedThreadId != 0);
+
+ _state = managedThreadId == 0 ? State.InitialStateValue : State.LockedStateValue;
+ _owningThreadId = (uint)managedThreadId;
+ _recursionCount = recursionCount;
+ }
+
+ internal struct ThreadId
+ {
+ private uint _id;
+
+ public ThreadId(uint id) => _id = id;
+ public uint Id => _id;
+ public bool IsInitialized => _id != 0;
+ public static ThreadId Current_NoInitialize => new ThreadId((uint)ManagedThreadId.CurrentManagedThreadIdUnchecked);
+
+ public void InitializeForCurrentThread()
+ {
+ Debug.Assert(!IsInitialized);
+ _id = (uint)ManagedThreadId.Current;
+ Debug.Assert(IsInitialized);
+ }
+ }
+
+ private enum StaticsInitializationStage
+ {
+ NotStarted,
+ Started,
+ Complete
+ }
+ }
+}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.cs
deleted file mode 100644
index 30bc946ad42546..00000000000000
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.cs
+++ /dev/null
@@ -1,544 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.IO;
-using System.Runtime;
-using System.Runtime.CompilerServices;
-
-namespace System.Threading
-{
- public sealed class Lock : IDisposable
- {
- //
- // This lock is a hybrid spinning/blocking lock with dynamically adjusted spinning.
- // On a multiprocessor machine an acquiring thread will try to acquire multiple times
- // before going to sleep. The amount of spinning is dynamically adjusted based on past
- // history of the lock and will stay in the following range.
- //
- // We use doubling-up delays with a cap while spinning (1,2,4,8,16,32,64,64,64,64, ...)
- // Thus 20 iterations is about 1000 speenwaits (20-50 ns each)
- // Context switch costs may vary and typically in 2-20 usec range
- // Even if we are the only thread trying to acquire the lock at 20-50 usec the cost of being
- // blocked+awaken may not be more than 2x of what we have already spent, so that is the max CPU time
- // that we will allow to burn while spinning.
- //
- // This may not be always optimal, but should be close enough.
- // I.E. in a system consisting of exactly 2 threads, unlimited spinning may work better, but we
- // will not optimize specifically for that.
- private const ushort MaxSpinLimit = 20;
- private const ushort MinSpinLimit = 3;
- private const ushort SpinningNotInitialized = MaxSpinLimit + 1;
- private const ushort SpinningDisabled = 0;
-
- //
- // We will use exponential backoff in rare cases when we need to change state atomically and cannot
- // make progress due to concurrent state changes by other threads.
- // While we cannot know the ideal amount of wait needed before making a successfull attempt,
- // the exponential backoff will generally be not more than 2X worse than the perfect guess and
- // will do a lot less attempts than an simple retry. On multiprocessor machine fruitless attempts
- // will cause unnecessary sharing of the contended state which may make modifying the state more expensive.
- // To protect against degenerate cases we will cap the per-iteration wait to 1024 spinwaits.
- //
- private const uint MaxExponentialBackoffBits = 10;
-
- //
- // This lock is unfair and permits acquiring a contended lock by a nonwaiter in the presence of waiters.
- // It is possible for one thread to keep holding the lock long enough that waiters go to sleep and
- // then release and reacquire fast enough that waiters have no chance to get the lock.
- // In extreme cases one thread could keep retaking the lock starving everybody else.
- // If we see woken waiters not able to take the lock for too long we will ask nonwaiters to wait.
- //
- private const uint WaiterWatchdogTicks = 100;
-
- //
- // NOTE: Lock must not have a static (class) constructor, as Lock itself is used to synchronize
- // class construction. If Lock has its own class constructor, this can lead to infinite recursion.
- // All static data in Lock must be lazy-initialized.
- //
- internal static int s_processorCount;
-
- //
- // m_state layout:
- //
- // bit 0: True if the lock is held, false otherwise.
- //
- // bit 1: True if we've set the event to wake a waiting thread. The waiter resets this to false when it
- // wakes up. This avoids the overhead of setting the event multiple times.
- //
- // bit 2: True if nonwaiters must not get ahead of waiters when acquiring a contended lock.
- //
- // everything else: A count of the number of threads waiting on the event.
- //
- private const int Uncontended = 0;
- private const int Locked = 1;
- private const int WaiterWoken = 2;
- private const int YieldToWaiters = 4;
- private const int WaiterCountIncrement = 8;
-
- // state of the lock
- private AutoResetEvent? _lazyEvent;
- private int _owningThreadId;
- private uint _recursionCount;
- private int _state;
- private ushort _spinLimit = SpinningNotInitialized;
- private short _wakeWatchDog;
-
- // used to transfer the state when inflating thin locks
- internal void InitializeLocked(int threadId, int recursionCount)
- {
- Debug.Assert(recursionCount == 0 || threadId != 0);
-
- _state = threadId == 0 ? Uncontended : Locked;
- _owningThreadId = threadId;
- _recursionCount = (uint)recursionCount;
- }
-
- private AutoResetEvent Event
- {
- get
- {
- if (_lazyEvent == null)
- Interlocked.CompareExchange(ref _lazyEvent, new AutoResetEvent(false), null);
-
- return _lazyEvent;
- }
- }
-
- public void Dispose()
- {
- _lazyEvent?.Dispose();
- }
-
- private static int CurrentThreadId => Environment.CurrentManagedThreadId;
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Acquire()
- {
- int currentThreadId = CurrentThreadId;
- if (TryAcquireOneShot(currentThreadId))
- return;
-
- //
- // Fall back to the slow path for contention
- //
- bool success = TryAcquireSlow(currentThreadId, Timeout.Infinite);
- Debug.Assert(success);
- }
-
- public bool TryAcquire(TimeSpan timeout)
- {
- return TryAcquire(WaitHandle.ToTimeoutMilliseconds(timeout));
- }
-
- public bool TryAcquire(int millisecondsTimeout)
- {
- ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1);
-
- int currentThreadId = CurrentThreadId;
- if (TryAcquireOneShot(currentThreadId))
- return true;
-
- //
- // Fall back to the slow path for contention
- //
- return TryAcquireSlow(currentThreadId, millisecondsTimeout, trackContentions: false);
- }
-
- internal bool TryAcquireNoSpin()
- {
- //
- // Make one quick attempt to acquire an uncontended lock
- //
- int currentThreadId = CurrentThreadId;
- if (TryAcquireOneShot(currentThreadId))
- return true;
-
- //
- // If we already own the lock, just increment the recursion count.
- //
- if (_owningThreadId == currentThreadId)
- {
- checked { _recursionCount++; }
- return true;
- }
-
- return false;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool TryAcquireOneShot(int currentThreadId)
- {
- int origState = _state;
- int expectedState = origState & ~(YieldToWaiters | Locked);
- int newState = origState | Locked;
- if (Interlocked.CompareExchange(ref _state, newState, expectedState) == expectedState)
- {
- Debug.Assert(_owningThreadId == 0);
- Debug.Assert(_recursionCount == 0);
- _owningThreadId = currentThreadId;
- return true;
- }
-
- return false;
- }
-
- private static unsafe void ExponentialBackoff(uint iteration)
- {
- if (iteration > 0)
- {
- // no need for much randomness here, we will just hash the stack address + iteration.
- uint rand = ((uint)&iteration + iteration) * 2654435769u;
- // set the highmost bit to ensure minimum number of spins is exponentialy increasing
- // that is in case some stack location results in a sequence of very low spin counts
- // it basically gurantees that we spin at least 1, 2, 4, 8, 16, times, and so on
- rand |= (1u << 31);
- uint spins = rand >> (byte)(32 - Math.Min(iteration, MaxExponentialBackoffBits));
- Thread.SpinWaitInternal((int)spins);
- }
- }
-
- internal bool TryAcquireSlow(int currentThreadId, int millisecondsTimeout, bool trackContentions = false)
- {
- //
- // If we already own the lock, just increment the recursion count.
- //
- if (_owningThreadId == currentThreadId)
- {
- checked { _recursionCount++; }
- return true;
- }
-
- //
- // We've already made one lock attempt at this point, so bail early if the timeout is zero.
- //
- if (millisecondsTimeout == 0)
- return false;
-
- // since we have just made an attempt to accuire and failed, do a small pause
- Thread.SpinWaitInternal(1);
-
- if (_spinLimit == SpinningNotInitialized)
- {
- // Use RhGetProcessCpuCount directly to avoid Environment.ProcessorCount->ClassConstructorRunner->Lock->Environment.ProcessorCount cycle
- if (s_processorCount == 0)
- s_processorCount = RuntimeImports.RhGetProcessCpuCount();
-
- _spinLimit = (s_processorCount > 1) ? MinSpinLimit : SpinningDisabled;
- }
-
- bool hasWaited = false;
- // we will retry after waking up
- while (true)
- {
- uint iteration = 0;
-
- // We will count when we failed to change the state of the lock and increase pauses
- // so that bursts of activity are better tolerated. This should not happen often.
- uint collisions = 0;
-
- // We will track the changes of ownership while we are trying to acquire the lock.
- int oldOwner = _owningThreadId;
- uint ownerChanged = 0;
-
- uint localSpinLimit = _spinLimit;
- // inner loop where we try acquiring the lock or registering as a waiter
- while (true)
- {
- //
- // Try to grab the lock. We may take the lock here even if there are existing waiters. This creates the possibility
- // of starvation of waiters, but it also prevents lock convoys and preempted waiters from destroying perf.
- // However, if we do not see _wakeWatchDog cleared for long enough, we go into YieldToWaiters mode to ensure some
- // waiter progress.
- //
- int oldState = _state;
- bool canAcquire = ((oldState & Locked) == 0) &&
- (hasWaited || ((oldState & YieldToWaiters) == 0));
-
- if (canAcquire)
- {
- int newState = oldState | Locked;
- if (hasWaited)
- newState = (newState - WaiterCountIncrement) & ~(WaiterWoken | YieldToWaiters);
-
- if (Interlocked.CompareExchange(ref _state, newState, oldState) == oldState)
- {
- // GOT THE LOCK!!
- if (hasWaited)
- _wakeWatchDog = 0;
-
- // now we can estimate how busy the lock is and adjust spinning accordingly
- ushort spinLimit = _spinLimit;
- if (ownerChanged != 0)
- {
- // The lock has changed ownership while we were trying to acquire it.
- // It is a signal that we might want to spin less next time.
- // Pursuing a lock that is being "stolen" by other threads is inefficient
- // due to cache misses and unnecessary sharing of state that keeps invalidating.
- if (spinLimit > MinSpinLimit)
- {
- _spinLimit = (ushort)(spinLimit - 1);
- }
- }
- else if (spinLimit < MaxSpinLimit && iteration > spinLimit / 2)
- {
- // we used more than 50% of allowed iterations, but the lock does not look very contested,
- // we can allow a bit more spinning.
- _spinLimit = (ushort)(spinLimit + 1);
- }
-
- Debug.Assert((_state | Locked) != 0);
- Debug.Assert(_owningThreadId == 0);
- Debug.Assert(_recursionCount == 0);
- _owningThreadId = currentThreadId;
- return true;
- }
- }
-
- if (iteration++ < localSpinLimit)
- {
- int newOwner = _owningThreadId;
- if (newOwner != 0 && newOwner != oldOwner)
- {
- ownerChanged++;
- oldOwner = newOwner;
- }
-
- if (canAcquire)
- {
- collisions++;
- }
-
- // We failed to acquire the lock and want to retry after a pause.
- // Ideally we will retry right when the lock becomes free, but we cannot know when that will happen.
- // We will use a pause that doubles up on every iteration. It will not be more than 2x worse
- // than the ideal guess, while minimizing the number of retries.
- // We will allow pauses up to 64~128 spinwaits, or more if there are collisions.
- ExponentialBackoff(Math.Min(iteration, 6) + collisions);
- continue;
- }
- else if (!canAcquire)
- {
- //
- // We reached our spin limit, and need to wait. Increment the waiter count.
- // Note that we do not do any overflow checking on this increment. In order to overflow,
- // we'd need to have about 1 billion waiting threads, which is inconceivable anytime in the
- // forseeable future.
- //
- int newState = oldState + WaiterCountIncrement;
- if (hasWaited)
- newState = (newState - WaiterCountIncrement) & ~WaiterWoken;
-
- if (Interlocked.CompareExchange(ref _state, newState, oldState) == oldState)
- break;
-
- collisions++;
- }
-
- ExponentialBackoff(collisions);
- }
-
- //
- // Now we wait.
- //
-
- if (trackContentions)
- {
- Monitor.IncrementLockContentionCount();
- }
-
- TimeoutTracker timeoutTracker = TimeoutTracker.Start(millisecondsTimeout);
- Debug.Assert(_state >= WaiterCountIncrement);
- bool waitSucceeded = Event.WaitOne(millisecondsTimeout);
- Debug.Assert(_state >= WaiterCountIncrement);
-
- if (!waitSucceeded)
- break;
-
- // we did not time out and will try acquiring the lock
- hasWaited = true;
- millisecondsTimeout = timeoutTracker.Remaining;
- }
-
- // We timed out. We're not going to wait again.
- {
- uint iteration = 0;
- while (true)
- {
- int oldState = _state;
- Debug.Assert(oldState >= WaiterCountIncrement);
-
- int newState = oldState - WaiterCountIncrement;
-
- // We could not have consumed a wake, or the wait would've succeeded.
- // If we are the last waiter though, we will clear WaiterWoken and YieldToWaiters
- // just so that lock would not look like contended.
- if (newState < WaiterCountIncrement)
- newState = newState & ~WaiterWoken & ~YieldToWaiters;
-
- if (Interlocked.CompareExchange(ref _state, newState, oldState) == oldState)
- return false;
-
- ExponentialBackoff(iteration++);
- }
- }
- }
-
- public bool IsAcquired
- {
- get
- {
- //
- // Compare the current owning thread ID with the current thread ID. We need
- // to read the current thread's ID before we read m_owningThreadId. Otherwise,
- // the following might happen:
- //
- // 1) We read m_owningThreadId, and get, say 42, which belongs to another thread.
- // 2) Thread 42 releases the lock, and exits.
- // 3) We call ManagedThreadId.Current. If this is the first time it's been called
- // on this thread, we'll go get a new ID. We may reuse thread 42's ID, since
- // that thread is dead.
- // 4) Now we're thread 42, and it looks like we own the lock, even though we don't.
- //
- // However, as long as we get this thread's ID first, we know it won't be reused,
- // because while we're doing this check the current thread is definitely still
- // alive.
- //
- int currentThreadId = CurrentThreadId;
- return IsAcquiredByThread(currentThreadId);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool IsAcquiredByThread(int currentThreadId)
- {
- bool acquired = (currentThreadId == _owningThreadId);
- Debug.Assert(!acquired || (_state & Locked) != 0);
- return acquired;
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Release()
- {
- ReleaseByThread(CurrentThreadId);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ReleaseByThread(int threadId)
- {
- if (threadId != _owningThreadId)
- throw new SynchronizationLockException();
-
- if (_recursionCount == 0)
- {
- ReleaseCore();
- return;
- }
-
- _recursionCount--;
- }
-
- internal uint ReleaseAll()
- {
- Debug.Assert(IsAcquired);
-
- uint recursionCount = _recursionCount;
- _recursionCount = 0;
-
- ReleaseCore();
-
- return recursionCount;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ReleaseCore()
- {
- Debug.Assert(_recursionCount == 0);
- _owningThreadId = 0;
- int origState = Interlocked.Decrement(ref _state);
- if (origState < WaiterCountIncrement || (origState & WaiterWoken) != 0)
- {
- return;
- }
-
- //
- // We have waiters; take the slow path.
- //
- AwakeWaiterIfNeeded();
- }
-
- private void AwakeWaiterIfNeeded()
- {
- uint iteration = 0;
- while (true)
- {
- int oldState = _state;
- if (oldState >= WaiterCountIncrement && (oldState & WaiterWoken) == 0)
- {
- // there are waiters, and nobody has woken one.
- int newState = oldState | WaiterWoken;
-
- short lastWakeTicks = _wakeWatchDog;
- if (lastWakeTicks != 0 && (short)Environment.TickCount - lastWakeTicks > WaiterWatchdogTicks)
- {
- newState |= YieldToWaiters;
- }
-
- if (Interlocked.CompareExchange(ref _state, newState, oldState) == oldState)
- {
- if (lastWakeTicks == 0)
- {
- // nonzero timestamp of the last wake
- _wakeWatchDog = (short)(Environment.TickCount | 1);
- }
-
- Event.Set();
- return;
- }
- }
- else
- {
- // no need to wake a waiter.
- return;
- }
-
- ExponentialBackoff(iteration++);
- }
- }
-
- internal void Reacquire(uint previousRecursionCount)
- {
- Acquire();
- Debug.Assert(_recursionCount == 0);
- _recursionCount = previousRecursionCount;
- }
-
- internal struct TimeoutTracker
- {
- private int _start;
- private int _timeout;
-
- public static TimeoutTracker Start(int timeout)
- {
- TimeoutTracker tracker = new TimeoutTracker();
- tracker._timeout = timeout;
- if (timeout != Timeout.Infinite)
- tracker._start = Environment.TickCount;
- return tracker;
- }
-
- public int Remaining
- {
- get
- {
- if (_timeout == Timeout.Infinite)
- return Timeout.Infinite;
- int elapsed = Environment.TickCount - _start;
- if (elapsed > _timeout)
- return 0;
- return _timeout - elapsed;
- }
- }
- }
- }
-}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/LockHolder.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/LockHolder.cs
deleted file mode 100644
index 784a5d0fe3555e..00000000000000
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/LockHolder.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Runtime.CompilerServices;
-
-namespace System.Threading
-{
- public struct LockHolder : IDisposable
- {
- private Lock _lock;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static LockHolder Hold(Lock l)
- {
- LockHolder h;
- l.Acquire();
- h._lock = l;
- return h;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Dispose()
- {
- _lock.Release();
- }
- }
-}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs
index ce2e58a975abf0..89a8505663d307 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs
@@ -41,7 +41,8 @@ private static Condition GetCondition(object obj)
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Enter(object obj)
{
- int resultOrIndex = ObjectHeader.Acquire(obj);
+ int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked;
+ int resultOrIndex = ObjectHeader.Acquire(obj, currentThreadID);
if (resultOrIndex < 0)
return;
@@ -49,7 +50,7 @@ public static void Enter(object obj)
ObjectHeader.GetLockObject(obj) :
SyncTable.GetLockObject(resultOrIndex);
- TryAcquireSlow(lck, obj, Timeout.Infinite);
+ lck.TryEnterSlow(Timeout.Infinite, currentThreadID, obj);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -66,7 +67,8 @@ public static void Enter(object obj, ref bool lockTaken)
[MethodImpl(MethodImplOptions.NoInlining)]
public static bool TryEnter(object obj)
{
- int resultOrIndex = ObjectHeader.TryAcquire(obj);
+ int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked;
+ int resultOrIndex = ObjectHeader.TryAcquire(obj, currentThreadID);
if (resultOrIndex < 0)
return true;
@@ -74,7 +76,13 @@ public static bool TryEnter(object obj)
return false;
Lock lck = SyncTable.GetLockObject(resultOrIndex);
- return lck.TryAcquire(0);
+
+ // The one-shot fast path is not covered by the slow path below for a zero timeout when the thread ID is
+ // initialized, so cover it here in case it wasn't already done
+ if (currentThreadID != 0 && lck.TryEnterOneShot(currentThreadID))
+ return true;
+
+ return lck.TryEnterSlow(0, currentThreadID, obj);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -92,7 +100,8 @@ public static bool TryEnter(object obj, int millisecondsTimeout)
{
ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1);
- int resultOrIndex = ObjectHeader.TryAcquire(obj);
+ int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked;
+ int resultOrIndex = ObjectHeader.TryAcquire(obj, currentThreadID);
if (resultOrIndex < 0)
return true;
@@ -100,10 +109,12 @@ public static bool TryEnter(object obj, int millisecondsTimeout)
ObjectHeader.GetLockObject(obj) :
SyncTable.GetLockObject(resultOrIndex);
- if (millisecondsTimeout == 0)
- return lck.TryAcquireNoSpin();
+ // The one-shot fast path is not covered by the slow path below for a zero timeout when the thread ID is
+ // initialized, so cover it here in case it wasn't already done
+ if (millisecondsTimeout == 0 && currentThreadID != 0 && lck.TryEnterOneShot(currentThreadID))
+ return true;
- return TryAcquireSlow(lck, obj, millisecondsTimeout);
+ return lck.TryEnterSlow(millisecondsTimeout, currentThreadID, obj);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -159,18 +170,6 @@ public static void PulseAll(object obj)
#endregion
- #region Slow path for Entry/TryEnter methods.
-
- internal static bool TryAcquireSlow(Lock lck, object obj, int millisecondsTimeout)
- {
- using (new DebugBlockingScope(obj, DebugBlockingItemType.MonitorCriticalSection, millisecondsTimeout, out _))
- {
- return lck.TryAcquireSlow(Environment.CurrentManagedThreadId, millisecondsTimeout, trackContentions: true);
- }
- }
-
- #endregion
-
#region Debugger support
// The debugger binds to the fields below by name. Do not change any names or types without
@@ -185,14 +184,14 @@ internal static bool TryAcquireSlow(Lock lck, object obj, int millisecondsTimeou
// Different ways a thread can be blocked that the debugger will expose.
// Do not change or add members without updating the debugger code.
- private enum DebugBlockingItemType
+ internal enum DebugBlockingItemType
{
MonitorCriticalSection = 0,
MonitorEvent = 1
}
// Represents an item a thread is blocked on. This structure is allocated on the stack and accessed by the debugger.
- private struct DebugBlockingItem
+ internal struct DebugBlockingItem
{
// The object the thread is waiting on
public object _object;
@@ -207,7 +206,7 @@ private struct DebugBlockingItem
public IntPtr _next;
}
- private unsafe struct DebugBlockingScope : IDisposable
+ internal unsafe struct DebugBlockingScope : IDisposable
{
public DebugBlockingScope(object obj, DebugBlockingItemType blockingType, int timeout, out DebugBlockingItem blockingItem)
{
@@ -229,28 +228,10 @@ public void Dispose()
#region Metrics
- private static readonly ThreadInt64PersistentCounter s_lockContentionCounter = new ThreadInt64PersistentCounter();
-
- [ThreadStatic]
- private static object t_ContentionCountObject;
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static object CreateThreadLocalContentionCountObject()
- {
- Debug.Assert(t_ContentionCountObject == null);
-
- object threadLocalContentionCountObject = s_lockContentionCounter.CreateThreadLocalCountObject();
- t_ContentionCountObject = threadLocalContentionCountObject;
- return threadLocalContentionCountObject;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static void IncrementLockContentionCount() => ThreadInt64PersistentCounter.Increment(t_ContentionCountObject ?? CreateThreadLocalContentionCountObject());
-
///
/// Gets the number of times there was contention upon trying to take a 's lock so far.
///
- public static long LockContentionCount => s_lockContentionCounter.Count;
+ public static long LockContentionCount => Lock.ContentionCount;
#endregion
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs
index 327586771fe074..d411f997ee11a4 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs
@@ -217,7 +217,7 @@ public static unsafe void SetSyncEntryIndex(int* pHeader, int syncIndex)
{
// Holding this lock implies there is at most one thread setting the sync entry index at
// any given time. We also require that the sync entry index has not been already set.
- Debug.Assert(SyncTable.s_lock.IsAcquired);
+ Debug.Assert(SyncTable.s_lock.IsHeldByCurrentThread);
int oldBits, newBits;
do
@@ -239,7 +239,7 @@ public static unsafe void SetSyncEntryIndex(int* pHeader, int syncIndex)
SyncTable.MoveThinLockToNewEntry(
syncIndex,
oldBits & SBLK_MASK_LOCK_THREADID,
- (oldBits & SBLK_MASK_LOCK_RECLEVEL) >> SBLK_RECLEVEL_SHIFT);
+ (uint)((oldBits & SBLK_MASK_LOCK_RECLEVEL) >> SBLK_RECLEVEL_SHIFT));
}
// Store the sync entry index
@@ -284,24 +284,22 @@ public static unsafe void SetSyncEntryIndex(int* pHeader, int syncIndex)
// 0 - failed
// syncIndex - retry with the Lock
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe int Acquire(object obj)
+ public static unsafe int Acquire(object obj, int currentThreadID)
{
- return TryAcquire(obj, oneShot: false);
+ return TryAcquire(obj, currentThreadID, oneShot: false);
}
// -1 - success
// 0 - failed
// syncIndex - retry with the Lock
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe int TryAcquire(object obj, bool oneShot = true)
+ public static unsafe int TryAcquire(object obj, int currentThreadID, bool oneShot = true)
{
ArgumentNullException.ThrowIfNull(obj);
Debug.Assert(!(obj is Lock),
"Do not use Monitor.Enter or TryEnter on a Lock instance; use Lock methods directly instead.");
- int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked;
-
// if thread ID is uninitialized or too big, we do "uncommon" part.
if ((uint)(currentThreadID - 1) <= (uint)SBLK_MASK_LOCK_THREADID)
{
@@ -323,7 +321,7 @@ public static unsafe int TryAcquire(object obj, bool oneShot = true)
}
else if (GetSyncEntryIndex(oldBits, out int syncIndex))
{
- if (SyncTable.GetLockObject(syncIndex).TryAcquireOneShot(currentThreadID))
+ if (SyncTable.GetLockObject(syncIndex).TryEnterOneShot(currentThreadID))
{
return -1;
}
@@ -334,23 +332,25 @@ public static unsafe int TryAcquire(object obj, bool oneShot = true)
}
}
- return TryAcquireUncommon(obj, oneShot);
+ return TryAcquireUncommon(obj, currentThreadID, oneShot);
}
// handling uncommon cases here - recursive lock, contention, retries
// -1 - success
// 0 - failed
// syncIndex - retry with the Lock
- private static unsafe int TryAcquireUncommon(object obj, bool oneShot)
+ private static unsafe int TryAcquireUncommon(object obj, int currentThreadID, bool oneShot)
{
+ if (currentThreadID == 0)
+ currentThreadID = Environment.CurrentManagedThreadId;
+
// does thread ID fit?
- int currentThreadID = Environment.CurrentManagedThreadId;
if (currentThreadID > SBLK_MASK_LOCK_THREADID)
return GetSyncIndex(obj);
- // Lock.s_processorCount is lazy-initialized at fist contended acquire
- // untill then it is 0 and we assume we have multicore machine
- int retries = oneShot || Lock.s_processorCount == 1 ? 0 : 16;
+ // Lock.IsSingleProcessor gets a value that is lazy-initialized at the first contended acquire.
+ // Until then it is false and we assume we have multicore machine.
+ int retries = oneShot || Lock.IsSingleProcessor ? 0 : 16;
// retry when the lock is owned by somebody else.
// this loop will spinwait between iterations.
@@ -422,9 +422,12 @@ private static unsafe int TryAcquireUncommon(object obj, bool oneShot)
}
}
- // spin a bit before retrying (1 spinwait is roughly 35 nsec)
- // the object is not pinned here
- Thread.SpinWaitInternal(i);
+ if (retries != 0)
+ {
+ // spin a bit before retrying (1 spinwait is roughly 35 nsec)
+ // the object is not pinned here
+ Thread.SpinWaitInternal(i);
+ }
}
// owned by somebody else
@@ -481,7 +484,7 @@ public static unsafe void Release(object obj)
}
}
- fatLock.ReleaseByThread(currentThreadID);
+ fatLock.Exit(currentThreadID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -510,7 +513,7 @@ public static unsafe bool IsAcquired(object obj)
if (GetSyncEntryIndex(oldBits, out int syncIndex))
{
- return SyncTable.GetLockObject(syncIndex).IsAcquiredByThread(currentThreadID);
+ return SyncTable.GetLockObject(syncIndex).GetIsHeldByCurrentThread(currentThreadID);
}
// someone else owns or noone.
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/SyncTable.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/SyncTable.cs
index de07c986834ec1..02d7b4167ca6b2 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/SyncTable.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/SyncTable.cs
@@ -106,7 +106,7 @@ public static unsafe int AssignEntry(object obj, int* pHeader)
try
{
- using (LockHolder.Hold(s_lock))
+ using (s_lock.EnterScope())
{
// After acquiring the lock check whether another thread already assigned the sync entry
if (ObjectHeader.GetSyncEntryIndex(*pHeader, out int syncIndex))
@@ -172,7 +172,7 @@ public static unsafe int AssignEntry(object obj, int* pHeader)
///
private static void Grow()
{
- Debug.Assert(s_lock.IsAcquired);
+ Debug.Assert(s_lock.IsHeldByCurrentThread);
int oldSize = s_entries.Length;
int newSize = CalculateNewSize(oldSize);
@@ -242,7 +242,7 @@ public static int SetHashCode(int syncIndex, int hashCode)
// Acquire the lock to ensure we are updating the latest version of s_entries. This
// lock may be avoided if we store the hash code and Monitor synchronization data in
// the same object accessed by a reference.
- using (LockHolder.Hold(s_lock))
+ using (s_lock.EnterScope())
{
int currentHash = s_entries[syncIndex].HashCode;
if (currentHash != 0)
@@ -260,7 +260,7 @@ public static int SetHashCode(int syncIndex, int hashCode)
///
public static void MoveHashCodeToNewEntry(int syncIndex, int hashCode)
{
- Debug.Assert(s_lock.IsAcquired);
+ Debug.Assert(s_lock.IsHeldByCurrentThread);
Debug.Assert((0 < syncIndex) && (syncIndex < s_unusedEntryIndex));
s_entries[syncIndex].HashCode = hashCode;
}
@@ -269,9 +269,9 @@ public static void MoveHashCodeToNewEntry(int syncIndex, int hashCode)
/// Initializes the Lock assuming the caller holds s_lock. Use for not yet
/// published entries only.
///
- public static void MoveThinLockToNewEntry(int syncIndex, int threadId, int recursionLevel)
+ public static void MoveThinLockToNewEntry(int syncIndex, int threadId, uint recursionLevel)
{
- Debug.Assert(s_lock.IsAcquired);
+ Debug.Assert(s_lock.IsHeldByCurrentThread);
Debug.Assert((0 < syncIndex) && (syncIndex < s_unusedEntryIndex));
s_entries[syncIndex].Lock.InitializeLocked(threadId, recursionLevel);
@@ -305,7 +305,7 @@ public DeadEntryCollector()
Lock? lockToDispose = default;
DependentHandle dependentHandleToDispose = default;
- using (LockHolder.Hold(s_lock))
+ using (s_lock.EnterScope())
{
ref Entry entry = ref s_entries[_index];
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
index 467e13cfd60338..7d8c2f2a2f290f 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
@@ -251,7 +251,7 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
if (this != CurrentThread)
{
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
if (HasStarted())
throw new ThreadStateException();
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs
index cda114276746c8..ef35ed5358fafc 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs
@@ -230,7 +230,7 @@ public ThreadPriority Priority
}
// Prevent race condition with starting this thread
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
if (HasStarted() && !SetPriorityLive(value))
{
@@ -358,7 +358,7 @@ public static void SpinWait(int iterations)
private void StartCore()
{
- using (LockHolder.Hold(_lock))
+ using (_lock.EnterScope())
{
if (!GetThreadStateBit(ThreadState.Unstarted))
{
diff --git a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj
index 163f809979cc42..25af7c63691ee8 100644
--- a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj
+++ b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj
@@ -2,6 +2,8 @@
false
+
+ true
diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
index 5527d5920f6018..2610014e0d3c14 100644
--- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
+++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
@@ -8,6 +8,8 @@
$(CompilerCommonPath)\Internal\NativeFormat
false
+
+ true
diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
index cc44031e9ac552..620a94d91c40ab 100644
--- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
+++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
@@ -2,6 +2,8 @@
false
+
+ true
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs
index 9fe72daf5045db..228da851da728f 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs
@@ -274,7 +274,7 @@ public bool TryGetGenericVirtualMethodPointer(InstantiatedMethod method, out Int
if (!TryLookupGenericMethodDictionary(new MethodDescBasedGenericMethodLookup(method), out dictionaryPointer))
{
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
// Now that we hold the lock, we may find that existing types can now find
// their associated RuntimeTypeHandle. Flush the type builder states as a way
@@ -297,7 +297,7 @@ private bool TryGetDynamicGenericMethodDictionary(GenericMethodLookupData lookup
{
result = IntPtr.Zero;
- using (LockHolder.Hold(_dynamicGenericsLock))
+ using (_dynamicGenericsLock.EnterScope())
{
GenericMethodEntry entry;
if (!_dynamicGenericMethods.TryGetValue(lookupData, out entry))
@@ -349,7 +349,7 @@ private bool TryGetDynamicGenericMethodComponents(IntPtr methodDictionary, out R
methodNameAndSignature = null;
genericMethodArgumentHandles = null;
- using (LockHolder.Hold(_dynamicGenericsLock))
+ using (_dynamicGenericsLock.EnterScope())
{
GenericMethodEntry entry;
if (!_dynamicGenericMethodComponents.TryGetValue(methodDictionary, out entry))
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs
index 2db0a24b5586d9..257803bd9026ef 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs
@@ -217,7 +217,7 @@ public bool TryLookupConstructedGenericTypeForComponents(RuntimeTypeHandle gener
public bool TryLookupConstructedLazyDictionaryForContext(IntPtr context, IntPtr signature, out IntPtr dictionary)
{
- Debug.Assert(_typeLoaderLock.IsAcquired);
+ Debug.Assert(_typeLoaderLock.IsHeldByCurrentThread);
return _lazyGenericDictionaries.TryGetValue(new LazyDictionaryContext { _context = context, _signature = signature }, out dictionary);
}
@@ -226,7 +226,7 @@ private unsafe bool TryGetDynamicGenericTypeForComponents(GenericTypeLookupData
{
runtimeTypeHandle = default(RuntimeTypeHandle);
- using (LockHolder.Hold(_dynamicGenericsLock))
+ using (_dynamicGenericsLock.EnterScope())
{
GenericTypeEntry entry;
if (!_dynamicGenericTypes.TryGetValue(lookupData, out entry))
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericsRegistration.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericsRegistration.cs
index 8c9922d1a29c73..cebd5d917896fe 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericsRegistration.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericsRegistration.cs
@@ -28,7 +28,7 @@ internal struct DynamicGenericsRegistrationData
internal void RegisterDynamicGenericTypesAndMethods(DynamicGenericsRegistrationData registrationData)
{
- using (LockHolder.Hold(_dynamicGenericsLock))
+ using (_dynamicGenericsLock.EnterScope())
{
int registeredTypesCount = 0;
int registeredMethodsCount = 0;
@@ -130,7 +130,7 @@ internal void RegisterDynamicGenericTypesAndMethods(DynamicGenericsRegistrationD
public void RegisterConstructedLazyDictionaryForContext(IntPtr context, IntPtr signature, IntPtr dictionary)
{
- Debug.Assert(_typeLoaderLock.IsAcquired);
+ Debug.Assert(_typeLoaderLock.IsHeldByCurrentThread);
_lazyGenericDictionaries.Add(new LazyDictionaryContext { _context = context, _signature = signature }, dictionary);
}
}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs
index 8cc5e5844218fa..ad8c68b171e5c0 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs
@@ -57,7 +57,7 @@ private static unsafe string GetStringFromMemoryInNativeFormat(IntPtr pointerToD
///
public IntPtr GetNativeFormatStringForString(string str)
{
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
IntPtr result;
if (_nativeFormatStrings.TryGetValue(str, out result))
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs
index 4a28836cb33ce9..28cd9bf3276380 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs
@@ -145,7 +145,7 @@ public IntPtr TryGetThreadStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
public IntPtr GetThreadStaticGCDescForDynamicType(TypeManagerHandle typeManagerHandle, uint index)
{
- using (LockHolder.Hold(_threadStaticsLock))
+ using (_threadStaticsLock.EnterScope())
{
return _dynamicGenericsThreadStaticDescs[typeManagerHandle.GetIntPtrUNSAFE()][index];
}
@@ -168,7 +168,7 @@ public void RegisterDynamicThreadStaticsInfo(RuntimeTypeHandle runtimeTypeHandle
IntPtr typeManager = runtimeTypeHandle.GetTypeManager().GetIntPtrUNSAFE();
- _threadStaticsLock.Acquire();
+ _threadStaticsLock.Enter();
try
{
if (!_dynamicGenericsThreadStaticDescs.TryGetValue(typeManager, out LowLevelDictionary gcDescs))
@@ -188,7 +188,7 @@ public void RegisterDynamicThreadStaticsInfo(RuntimeTypeHandle runtimeTypeHandle
}
}
- _threadStaticsLock.Release();
+ _threadStaticsLock.Exit();
}
}
#endregion
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs
index ab037c2b41e39c..1bd3cbd3672fac 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs
@@ -144,13 +144,13 @@ internal static void Initialize()
public void VerifyTypeLoaderLockHeld()
{
- if (!_typeLoaderLock.IsAcquired)
+ if (!_typeLoaderLock.IsHeldByCurrentThread)
Environment.FailFast("TypeLoaderLock not held");
}
public void RunUnderTypeLoaderLock(Action action)
{
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
action();
}
@@ -160,7 +160,7 @@ public IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntPtr signat
{
IntPtr result;
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
try
{
@@ -191,7 +191,7 @@ private bool EnsureTypeHandleForType(TypeDesc type)
{
if (type.RuntimeTypeHandle.IsNull())
{
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
// Now that we hold the lock, we may find that existing types can now find
// their associated RuntimeTypeHandle. Flush the type builder states as a way
@@ -340,7 +340,7 @@ public bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericT
if (TryLookupConstructedGenericTypeForComponents(genericTypeDefinitionHandle, genericTypeArgumentHandles, out runtimeTypeHandle))
return true;
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
return TypeBuilder.TryBuildGenericType(genericTypeDefinitionHandle, genericTypeArgumentHandles, out runtimeTypeHandle);
}
@@ -351,7 +351,7 @@ public bool TryGetFunctionPointerTypeForComponents(RuntimeTypeHandle returnTypeH
if (TryLookupFunctionPointerTypeForComponents(returnTypeHandle, parameterHandles, isUnmanaged, out runtimeTypeHandle))
return true;
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
return TypeBuilder.TryBuildFunctionPointerType(returnTypeHandle, parameterHandles, isUnmanaged, out runtimeTypeHandle);
}
@@ -390,7 +390,7 @@ public bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, b
return true;
}
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
if (isMdArray && (rank < MDArray.MinRank) && (rank > MDArray.MaxRank))
{
@@ -432,7 +432,7 @@ public bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle,
if (TryGetPointerTypeForTargetType_LookupOnly(pointeeTypeHandle, out pointerTypeHandle))
return true;
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
if (TypeSystemContext.PointerTypesCache.TryGetValue(pointeeTypeHandle, out pointerTypeHandle))
return true;
@@ -461,7 +461,7 @@ public bool TryGetByRefTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, ou
if (TryGetByRefTypeForTargetType_LookupOnly(pointeeTypeHandle, out byRefTypeHandle))
return true;
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
if (TypeSystemContext.ByRefTypesCache.TryGetValue(pointeeTypeHandle, out byRefTypeHandle))
return true;
@@ -525,7 +525,7 @@ public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declari
return true;
}
- using (LockHolder.Hold(_typeLoaderLock))
+ using (_typeLoaderLock.EnterScope())
{
bool success = TypeBuilder.TryBuildGenericMethod(methodBeingLoaded, out methodDictionary);
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs
index 4d3fa768fdd2d6..b0175eaaa48034 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs
@@ -22,7 +22,7 @@ public static class TypeSystemContextFactory
public static TypeSystemContext Create()
{
- using (LockHolder.Hold(s_lock))
+ using (s_lock.EnterScope())
{
TypeSystemContext context = (TypeSystemContext)s_cachedContext.Target;
if (context != null)
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
index 61799cfc159b1f..b25a5cfcf7d364 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
@@ -9,6 +9,8 @@
GENERICS_FORCE_USG;$(DefineConstants)
false
+
+ true
diff --git a/src/coreclr/tools/AssemblyChecker/AssemblyChecker.csproj b/src/coreclr/tools/AssemblyChecker/AssemblyChecker.csproj
new file mode 100644
index 00000000000000..821c47c95403cd
--- /dev/null
+++ b/src/coreclr/tools/AssemblyChecker/AssemblyChecker.csproj
@@ -0,0 +1,16 @@
+
+
+ AssemblyChecker
+ Exe
+ $(NetCoreAppToolCurrent)
+ AnyCPU
+ false
+ true
+ true
+ false
+ enable
+ enable
+ $(RuntimeBinDir)\AssemblyChecker
+ false
+
+
diff --git a/src/coreclr/tools/AssemblyChecker/Program.cs b/src/coreclr/tools/AssemblyChecker/Program.cs
new file mode 100644
index 00000000000000..69f86e050beb22
--- /dev/null
+++ b/src/coreclr/tools/AssemblyChecker/Program.cs
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+
+namespace AssemblyChecker
+{
+ ///
+ /// This is a simple console application that is designed to answer True or False
+ /// questions about whether a given file is a managed assembly or not.
+ /// You can also ask whether or not the assembly is debuggable.
+ /// Return code of 0 indicates the file is a managed assembly.
+ /// Return code of 1 indicates the file is not a managed assembly. No errors will be printed for this one.
+ ///
+ public class Program
+ {
+ private const string HelpText = @"
+Usage:
+ : Check if the file-path is a managed assembly.
+ --is-debug : Check if the file-path is a managed assembly that is built with debuggability.
+ --is-exe : Check if the file-path is a managed assembly that is an executable.
+";
+
+ static bool IsAssembly(string path)
+ {
+ using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+
+ // Try to read CLI metadata from the PE file.
+ using var peReader = new PEReader(fs);
+
+ if (!peReader.HasMetadata)
+ {
+ return false; // File does not have CLI metadata.
+ }
+
+ // Check that file has an assembly manifest.
+ MetadataReader reader = peReader.GetMetadataReader();
+ return reader.IsAssembly;
+ }
+
+ static bool IsDebug(string path)
+ {
+ return
+ Assembly.LoadFrom(path)
+ .GetCustomAttributes(typeof(DebuggableAttribute), false)
+ .OfType().Any(x => x.IsJITOptimizerDisabled);
+ }
+
+ static bool IsExe(string path)
+ {
+ using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+
+ // Try to read CLI metadata from the PE file.
+ using var peReader = new PEReader(fs);
+
+ if (!peReader.HasMetadata)
+ {
+ return false; // File does not have CLI metadata.
+ }
+
+ return peReader.PEHeaders.IsExe;
+ }
+
+ static int Main(string[] args)
+ {
+ if (args.Length == 0)
+ {
+ Console.WriteLine(HelpText);
+ Console.Error.WriteLine("\nExpected assembly file-path.");
+ return 2;
+ }
+
+ // Help
+ if (args.Contains("-h"))
+ {
+ Console.WriteLine(HelpText);
+ return 0;
+ }
+
+ if (args.Length == 1)
+ {
+ return IsAssembly(args[0]) ? 0 : 1;
+ }
+
+ if (args.Length == 2)
+ {
+ switch (args[0])
+ {
+ case "--is-debug":
+ {
+ return IsDebug(args[1]) ? 0 : 1;
+ }
+
+ case "--is-exe":
+ {
+ return IsExe(args[1]) ? 0 : 1;
+ }
+
+ default:
+ {
+ Console.WriteLine(HelpText);
+ Console.Error.WriteLine("\nInvalid option.");
+ return 2;
+ }
+ }
+ }
+
+ Console.WriteLine(HelpText);
+ Console.Error.WriteLine("\nToo many arguments.");
+ return 2;
+ }
+ }
+}
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index 9d98650b91bbb9..01d2d15fc2997e 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -707,9 +707,15 @@ private void CompileMethodCleanup()
_instantiationToJitVisibleInstantiation = null;
_pgoResults.Clear();
+
+ // We need to clear out this cache because the next compilation could actually come up
+ // with a different MethodIL for the same MethodDesc. This happens when we need to replace
+ // a MethodIL with a throw helper.
+ _methodILScopeToHandle.Clear();
}
private Dictionary
-
-
-
-
+
+
+
+
Common\System\Runtime\InteropServices\IDispatch.cs
-
- Common\System\Runtime\InteropServices\Variant.cs
+
+ Common\System\Runtime\InteropServices\BuiltInVariantExtensions.cs
@@ -234,7 +228,7 @@
-
+
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
index 9052ad6d7a0afb..ff356ef08c96c8 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
@@ -8,6 +8,7 @@
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
using ComTypes = System.Runtime.InteropServices.ComTypes;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -92,7 +93,7 @@ private ParameterExpression DispParamsVariable
private ParameterExpression InvokeResultVariable
{
- get { return EnsureVariable(ref _invokeResult, typeof(Variant), "invokeResult"); }
+ get { return EnsureVariable(ref _invokeResult, typeof(ComVariant), "invokeResult"); }
}
private ParameterExpression ReturnValueVariable
@@ -306,8 +307,8 @@ private Expression GenerateTryBlock()
//
Expression invokeResultObject =
Expression.Call(
- InvokeResultVariable,
- typeof(Variant).GetMethod(nameof(Variant.ToObject)));
+ typeof(BuiltInInteropVariantExtensions).GetMethod(nameof(BuiltInInteropVariantExtensions.ToObject)),
+ InvokeResultVariable);
VariantBuilder[] variants = _varEnumSelector.VariantBuilders;
@@ -360,7 +361,7 @@ private Expression GenerateFinallyBlock()
finallyStatements.Add(
Expression.Call(
InvokeResultVariable,
- typeof(Variant).GetMethod(nameof(Variant.Clear))
+ typeof(ComVariant).GetMethod(nameof(ComVariant.Dispose))
)
);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
index 114b869124aff7..d090f3300cdb29 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
@@ -8,6 +8,7 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
using System.Security;
using ComTypes = System.Runtime.InteropServices.ComTypes;
@@ -230,11 +231,11 @@ internal static class UnsafeMethods
#region public members
public static unsafe IntPtr ConvertInt32ByrefToPtr(ref int value) { return (IntPtr)System.Runtime.CompilerServices.Unsafe.AsPointer(ref value); }
- public static unsafe IntPtr ConvertVariantByrefToPtr(ref Variant value) { return (IntPtr)System.Runtime.CompilerServices.Unsafe.AsPointer(ref value); }
+ public static unsafe IntPtr ConvertVariantByrefToPtr(ref ComVariant value) { return (IntPtr)System.Runtime.CompilerServices.Unsafe.AsPointer(ref value); }
- internal static Variant GetVariantForObject(object obj)
+ internal static ComVariant GetVariantForObject(object obj)
{
- Variant variant = default;
+ ComVariant variant = default;
if (obj == null)
{
return variant;
@@ -243,7 +244,7 @@ internal static Variant GetVariantForObject(object obj)
return variant;
}
- internal static void InitVariantForObject(object obj, ref Variant variant)
+ internal static void InitVariantForObject(object obj, ref ComVariant variant)
{
Debug.Assert(obj != null);
@@ -252,7 +253,7 @@ internal static void InitVariantForObject(object obj, ref Variant variant)
// Therefore we are going to test for IDispatch before defaulting to GetNativeVariantForObject.
if (obj is IDispatch)
{
- variant.AsDispatch = obj;
+ variant = ComVariant.CreateRaw(VarEnum.VT_DISPATCH, obj is not null ? Marshal.GetIDispatchForObject(obj) : 0);
return;
}
@@ -260,7 +261,7 @@ internal static void InitVariantForObject(object obj, ref Variant variant)
}
// This method is intended for use through reflection and should not be used directly
- public static object GetObjectForVariant(Variant variant)
+ public static object GetObjectForVariant(ComVariant variant)
{
IntPtr ptr = UnsafeMethods.ConvertVariantByrefToPtr(ref variant);
return Marshal.GetObjectForNativeVariant(ptr);
@@ -287,18 +288,18 @@ public static unsafe int IDispatchInvoke(
int memberDispId,
ComTypes.INVOKEKIND flags,
ref ComTypes.DISPPARAMS dispParams,
- out Variant result,
+ out ComVariant result,
out ExcepInfo excepInfo,
out uint argErr)
{
Guid IID_NULL = default;
fixed (ComTypes.DISPPARAMS* pDispParams = &dispParams)
- fixed (Variant* pResult = &result)
+ fixed (ComVariant* pResult = &result)
fixed (ExcepInfo* pExcepInfo = &excepInfo)
fixed (uint* pArgErr = &argErr)
{
- var pfnIDispatchInvoke = (delegate* unmanaged)
+ var pfnIDispatchInvoke = (delegate* unmanaged)
(*(*(void***)dispatchPointer + 6 /* IDispatch.Invoke slot */));
int hresult = pfnIDispatchInvoke(dispatchPointer,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DynamicVariantExtensions.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DynamicVariantExtensions.cs
new file mode 100644
index 00000000000000..27647ed388f28e
--- /dev/null
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DynamicVariantExtensions.cs
@@ -0,0 +1,446 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+using Microsoft.CSharp.RuntimeBinder.ComInterop;
+
+namespace Microsoft.CSharp.RuntimeBinder.ComInterop
+{
+ internal static class DynamicVariantExtensions
+ {
+ ///
+ /// Primitive types are the basic COM types. It includes valuetypes like ints, but also reference types
+ /// like BStrs. It does not include composite types like arrays and user-defined COM types (IUnknown/IDispatch).
+ ///
+ public static bool IsPrimitiveType(this VarEnum varEnum)
+ {
+ switch (varEnum)
+ {
+ case VarEnum.VT_I1:
+ case VarEnum.VT_I2:
+ case VarEnum.VT_I4:
+ case VarEnum.VT_I8:
+ case VarEnum.VT_UI1:
+ case VarEnum.VT_UI2:
+ case VarEnum.VT_UI4:
+ case VarEnum.VT_UI8:
+ case VarEnum.VT_INT:
+ case VarEnum.VT_UINT:
+ case VarEnum.VT_BOOL:
+ case VarEnum.VT_ERROR:
+ case VarEnum.VT_R4:
+ case VarEnum.VT_R8:
+ case VarEnum.VT_DECIMAL:
+ case VarEnum.VT_CY:
+ case VarEnum.VT_DATE:
+ case VarEnum.VT_BSTR:
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void SetAsIConvertible(this ref ComVariant variant, IConvertible value)
+ {
+ Debug.Assert(variant.VarType == VarEnum.VT_EMPTY); // The setter can only be called once as VariantClear might be needed otherwise
+
+ TypeCode tc = value.GetTypeCode();
+ CultureInfo ci = CultureInfo.CurrentCulture;
+
+ switch (tc)
+ {
+ case TypeCode.Empty: break;
+ case TypeCode.Object: variant = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, Marshal.GetIUnknownForObject(value)); break;
+ case TypeCode.DBNull: variant = ComVariant.Null; break;
+ case TypeCode.Boolean: variant = ComVariant.Create(value.ToBoolean(ci)); break;
+ case TypeCode.Char: variant = ComVariant.Create(value.ToChar(ci)); break;
+ case TypeCode.SByte: variant = ComVariant.Create(value.ToSByte(ci)); break;
+ case TypeCode.Byte: variant = ComVariant.Create(value.ToByte(ci)); break;
+ case TypeCode.Int16: variant = ComVariant.Create(value.ToInt16(ci)); break;
+ case TypeCode.UInt16: variant = ComVariant.Create(value.ToUInt16(ci)); break;
+ case TypeCode.Int32: variant = ComVariant.Create(value.ToInt32(ci)); break;
+ case TypeCode.UInt32: variant = ComVariant.Create(value.ToUInt32(ci)); break;
+ case TypeCode.Int64: variant = ComVariant.Create(value.ToInt64(ci)); break;
+ case TypeCode.UInt64: variant = ComVariant.Create(value.ToInt64(ci)); break;
+ case TypeCode.Single: variant = ComVariant.Create(value.ToSingle(ci)); break;
+ case TypeCode.Double: variant = ComVariant.Create(value.ToDouble(ci)); break;
+ case TypeCode.Decimal: variant = ComVariant.Create(value.ToDecimal(ci)); break;
+ case TypeCode.DateTime: variant = ComVariant.Create(value.ToDateTime(ci)); break;
+ case TypeCode.String: variant = ComVariant.Create(new BStrWrapper(value.ToString(ci))); break;
+
+ default:
+ throw new NotSupportedException();
+ }
+ }
+ // VT_I1
+
+ public static void SetAsByrefI1(ref this ComVariant variant, ref sbyte value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_I1);
+ }
+
+ // VT_I2
+
+ public static void SetAsByrefI2(ref this ComVariant variant, ref short value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_I2);
+ }
+
+ // VT_I4
+
+ public static void SetAsByrefI4(ref this ComVariant variant, ref int value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_I4);
+ }
+
+ // VT_I8
+
+ public static void SetAsByrefI8(ref this ComVariant variant, ref long value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_I8);
+ }
+
+ // VT_UI1
+
+ public static void SetAsByrefUi1(ref this ComVariant variant, ref byte value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UI1);
+ }
+
+ // VT_UI2
+
+ public static void SetAsByrefUi2(ref this ComVariant variant, ref ushort value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UI2);
+ }
+
+ // VT_UI4
+
+ public static void SetAsByrefUi4(ref this ComVariant variant, ref uint value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UI4);
+ }
+
+ // VT_UI8
+
+ public static void SetAsByrefUi8(ref this ComVariant variant, ref ulong value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UI8);
+ }
+
+ // VT_INT
+
+ public static void SetAsByrefInt(ref this ComVariant variant, ref int value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_INT);
+ }
+
+ // VT_UINT
+
+ public static void SetAsByrefUint(ref this ComVariant variant, ref uint value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UINT);
+ }
+
+ // VT_BOOL
+
+ public static void SetAsByrefBool(ref this ComVariant variant, ref short value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_BOOL);
+ }
+
+ // VT_ERROR
+
+ public static void SetAsByrefError(ref this ComVariant variant, ref int value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_ERROR);
+ }
+
+ // VT_R4
+
+ public static void SetAsByrefR4(ref this ComVariant variant, ref float value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_R4);
+ }
+
+ // VT_R8
+
+ public static void SetAsByrefR8(ref this ComVariant variant, ref double value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_R8);
+ }
+
+ // VT_DECIMAL
+
+ public static void SetAsByrefDecimal(ref this ComVariant variant, ref decimal value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_DECIMAL);
+ }
+
+ // VT_CY
+
+ public static void SetAsByrefCy(ref this ComVariant variant, ref long value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_CY);
+ }
+
+ // VT_DATE
+
+ public static void SetAsByrefDate(ref this ComVariant variant, ref double value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_DATE);
+ }
+
+ // VT_BSTR
+
+ public static void SetAsByrefBstr(ref this ComVariant variant, ref IntPtr value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_BSTR);
+ }
+
+ // VT_UNKNOWN
+
+ public static void SetAsByrefUnknown(ref this ComVariant variant, ref IntPtr value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_UNKNOWN);
+ }
+
+ // VT_DISPATCH
+
+ public static void SetAsByrefDispatch(ref this ComVariant variant, ref IntPtr value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_DISPATCH);
+ }
+
+ private static unsafe void SetAsByref(ref this ComVariant variant, ref T value, VarEnum type)
+ {
+ Debug.Assert(variant.VarType == VarEnum.VT_EMPTY); // The setter can only be called once as VariantClear might be needed otherwise
+ variant = ComVariant.CreateRaw(type | VarEnum.VT_BYREF, (nint)Unsafe.AsPointer(ref value));
+ }
+
+ public static void SetAsByrefVariant(ref this ComVariant variant, ref ComVariant value)
+ {
+ variant.SetAsByref(ref value, VarEnum.VT_VARIANT);
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct Record
+ {
+ public IntPtr _record;
+ public IntPtr _recordInfo;
+ }
+
+ // constructs a ByRef variant to pass contents of another variant ByRef.
+ public static unsafe void SetAsByrefVariantIndirect(ref this ComVariant variant, ref ComVariant value)
+ {
+ Debug.Assert(variant.VarType == VarEnum.VT_EMPTY); // The setter can only be called once as VariantClear might be needed otherwise
+ Debug.Assert((value.VarType & VarEnum.VT_BYREF) == 0, "double indirection");
+
+ switch (value.VarType)
+ {
+ case VarEnum.VT_EMPTY:
+ case VarEnum.VT_NULL:
+ // these cannot combine with VT_BYREF. Should try passing as a variant reference
+ variant.SetAsByrefVariant(ref value);
+ return;
+ case VarEnum.VT_RECORD:
+ // VT_RECORD's are weird in that regardless of is the VT_BYREF flag is set or not
+ // they have the same internal representation.
+ variant = ComVariant.CreateRaw(value.VarType | VarEnum.VT_BYREF, value.GetRawDataRef());
+ break;
+ case VarEnum.VT_DECIMAL:
+ // The DECIMAL value in an OLE Variant is stored at the start of the structure.
+ variant = ComVariant.CreateRaw(value.VarType | VarEnum.VT_BYREF, (nint)Unsafe.AsPointer(ref value));
+ break;
+ default:
+ variant = ComVariant.CreateRaw(value.VarType | VarEnum.VT_BYREF, (nint)Unsafe.AsPointer(ref value.GetRawDataRef()));
+ break;
+ }
+ }
+
+ internal static System.Reflection.MethodInfo GetByrefSetter(VarEnum varType)
+ {
+ switch (varType)
+ {
+ case VarEnum.VT_I1: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefI1));
+ case VarEnum.VT_I2: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefI2));
+ case VarEnum.VT_I4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefI4));
+ case VarEnum.VT_I8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefI8));
+ case VarEnum.VT_UI1: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUi1));
+ case VarEnum.VT_UI2: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUi2));
+ case VarEnum.VT_UI4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUi4));
+ case VarEnum.VT_UI8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUi8));
+ case VarEnum.VT_INT: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefInt));
+ case VarEnum.VT_UINT: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUint));
+ case VarEnum.VT_BOOL: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefBool));
+ case VarEnum.VT_ERROR: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefError));
+ case VarEnum.VT_R4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefR4));
+ case VarEnum.VT_R8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefR8));
+ case VarEnum.VT_DECIMAL: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefDecimal));
+ case VarEnum.VT_CY: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefCy));
+ case VarEnum.VT_DATE: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefDate));
+ case VarEnum.VT_BSTR: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefBstr));
+ case VarEnum.VT_UNKNOWN: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefUnknown));
+ case VarEnum.VT_DISPATCH: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefDispatch));
+
+ case VarEnum.VT_VARIANT:
+ return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefVariant));
+ case VarEnum.VT_RECORD:
+ case VarEnum.VT_ARRAY:
+ return typeof(DynamicVariantExtensions).GetMethod(nameof(SetAsByrefVariantIndirect));
+
+ default:
+ throw new NotSupportedException();
+ }
+ }
+
+ public static void SetI1(this ref ComVariant variant, sbyte value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetUi1(this ref ComVariant variant, byte value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetI2(this ref ComVariant variant, short value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetUi2(this ref ComVariant variant, ushort value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetI4(this ref ComVariant variant, int value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetUi4(this ref ComVariant variant, uint value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetI8(this ref ComVariant variant, long value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetUi8(this ref ComVariant variant, ulong value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetInt(this ref ComVariant variant, int value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_INT, value);
+ }
+
+ public static void SetUint(this ref ComVariant variant, uint value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_UINT, value);
+ }
+
+ public static void SetBool(this ref ComVariant variant, bool value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetR4(this ref ComVariant variant, float value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetR8(this ref ComVariant variant, double value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetDecimal(this ref ComVariant variant, decimal value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetDate(this ref ComVariant variant, DateTime value)
+ {
+ variant = ComVariant.Create(value);
+ }
+
+ public static void SetBstr(this ref ComVariant variant, string value)
+ {
+ variant = ComVariant.Create(new BStrWrapper(value));
+ }
+
+ public static void SetUnknown(this ref ComVariant variant, object value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, Marshal.GetIUnknownForObject(value));
+ }
+
+ public static void SetDispatch(this ref ComVariant variant, object value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_DISPATCH, Marshal.GetIDispatchForObject(value));
+ }
+
+ public static void SetError(this ref ComVariant variant, int value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_ERROR, value);
+ }
+
+ public static void SetCy(this ref ComVariant variant, decimal value)
+ {
+ variant = ComVariant.CreateRaw(VarEnum.VT_CY, decimal.ToOACurrency(value));
+ }
+
+ public static unsafe void SetVariant(this ref ComVariant variant, object value)
+ {
+ Debug.Assert(variant.VarType == VarEnum.VT_EMPTY); // The setter can only be called once as VariantClear might be needed otherwise
+ if (value != null)
+ {
+ UnsafeMethods.InitVariantForObject(value, ref variant);
+ }
+ }
+
+ internal static System.Reflection.MethodInfo GetSetter(VarEnum varType)
+ {
+ switch (varType)
+ {
+ case VarEnum.VT_I1: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetI1), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_I2: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetI2), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_I4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetI4), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_I8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetI8), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UI1: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUi1), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UI2: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUi2), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UI4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUi4), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UI8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUi8), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_INT: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetInt), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UINT: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUint), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_BOOL: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetBool), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_ERROR: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetError), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_R4: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetR4), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_R8: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetR8), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_DECIMAL: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetDecimal), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_CY: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetCy), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_DATE: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetDate), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_BSTR: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetBstr), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_UNKNOWN: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetUnknown), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ case VarEnum.VT_DISPATCH: return typeof(DynamicVariantExtensions).GetMethod(nameof(SetDispatch), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+
+ case VarEnum.VT_VARIANT:
+ case VarEnum.VT_RECORD:
+ case VarEnum.VT_ARRAY:
+ return typeof(DynamicVariantExtensions).GetMethod(nameof(SetVariant), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+
+ default:
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
index 85846d888f90ec..6f69602277aba2 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
@@ -46,7 +46,7 @@ internal VarEnumSelector(Type[] explicitArgTypes)
///
/// Gets the managed type that an object needs to be converted to in order for it to be able
- /// to be represented as a Variant.
+ /// to be represented as an ComVariant.
///
/// In general, there is a many-to-many mapping between Type and VarEnum. However, this method
/// returns a simple mapping that is needed for the current implementation. The reason for the
@@ -65,7 +65,7 @@ internal static Type GetManagedMarshalType(VarEnum varEnum)
return typeof(CurrencyWrapper);
}
- if (Variant.IsPrimitiveType(varEnum))
+ if (varEnum.IsPrimitiveType())
{
return s_comToManagedPrimitiveTypes[varEnum];
}
@@ -375,7 +375,7 @@ private static VarEnum GetComType(ref Type argumentType)
}
///
- /// Get the COM Variant type that argument should be marshaled as for a call to COM
+ /// Get the ComVariant type that argument should be marshaled as for a call to COM
///
[RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static VariantBuilder GetVariantBuilder(Type argumentType)
@@ -447,7 +447,7 @@ private static ArgBuilder GetByValArgBuilder(Type elementType, ref VarEnum eleme
return GetSimpleArgBuilder(elementType, elementVarEnum);
}
- // This helper can produce a builder for types that are directly supported by Variant.
+ // This helper can produce a builder for types that are directly supported by ComVariant or our extension methods.
private static SimpleArgBuilder GetSimpleArgBuilder(Type elementType, VarEnum elementVarEnum)
{
SimpleArgBuilder argBuilder;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/Variant.Extended.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/Variant.Extended.cs
deleted file mode 100644
index becef48a1466c2..00000000000000
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/Variant.Extended.cs
+++ /dev/null
@@ -1,319 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-
-using Microsoft.CSharp.RuntimeBinder.ComInterop;
-
-namespace System.Runtime.InteropServices
-{
- internal partial struct Variant
- {
- // VT_I1
-
- public void SetAsByrefI1(ref sbyte value)
- {
- SetAsByref(ref value, VarEnum.VT_I1);
- }
-
- // VT_I2
-
- public void SetAsByrefI2(ref short value)
- {
- SetAsByref(ref value, VarEnum.VT_I2);
- }
-
- // VT_I4
-
- public void SetAsByrefI4(ref int value)
- {
- SetAsByref(ref value, VarEnum.VT_I4);
- }
-
- // VT_I8
-
- public void SetAsByrefI8(ref long value)
- {
- SetAsByref(ref value, VarEnum.VT_I8);
- }
-
- // VT_UI1
-
- public void SetAsByrefUi1(ref byte value)
- {
- SetAsByref(ref value, VarEnum.VT_UI1);
- }
-
- // VT_UI2
-
- public void SetAsByrefUi2(ref ushort value)
- {
- SetAsByref(ref value, VarEnum.VT_UI2);
- }
-
- // VT_UI4
-
- public void SetAsByrefUi4(ref uint value)
- {
- SetAsByref(ref value, VarEnum.VT_UI4);
- }
-
- // VT_UI8
-
- public void SetAsByrefUi8(ref ulong value)
- {
- SetAsByref(ref value, VarEnum.VT_UI8);
- }
-
- // VT_INT
-
- public void SetAsByrefInt(ref int value)
- {
- SetAsByref(ref value, VarEnum.VT_INT);
- }
-
- // VT_UINT
-
- public void SetAsByrefUint(ref uint value)
- {
- SetAsByref(ref value, VarEnum.VT_UINT);
- }
-
- // VT_BOOL
-
- public void SetAsByrefBool(ref short value)
- {
- SetAsByref(ref value, VarEnum.VT_BOOL);
- }
-
- // VT_ERROR
-
- public void SetAsByrefError(ref int value)
- {
- SetAsByref(ref value, VarEnum.VT_ERROR);
- }
-
- // VT_R4
-
- public void SetAsByrefR4(ref float value)
- {
- SetAsByref(ref value, VarEnum.VT_R4);
- }
-
- // VT_R8
-
- public void SetAsByrefR8(ref double value)
- {
- SetAsByref(ref value, VarEnum.VT_R8);
- }
-
- // VT_DECIMAL
-
- public void SetAsByrefDecimal(ref decimal value)
- {
- SetAsByref(ref value, VarEnum.VT_DECIMAL);
- }
-
- // VT_CY
-
- public void SetAsByrefCy(ref long value)
- {
- SetAsByref(ref value, VarEnum.VT_CY);
- }
-
- // VT_DATE
-
- public void SetAsByrefDate(ref double value)
- {
- SetAsByref(ref value, VarEnum.VT_DATE);
- }
-
- // VT_BSTR
-
- public void SetAsByrefBstr(ref IntPtr value)
- {
- SetAsByref(ref value, VarEnum.VT_BSTR);
- }
-
- // VT_UNKNOWN
-
- public void SetAsByrefUnknown(ref IntPtr value)
- {
- SetAsByref(ref value, VarEnum.VT_UNKNOWN);
- }
-
- // VT_DISPATCH
-
- public void SetAsByrefDispatch(ref IntPtr value)
- {
- SetAsByref(ref value, VarEnum.VT_DISPATCH);
- }
-
- // VT_VARIANT
-
- public object AsVariant
- {
- get
- {
- return Marshal.GetObjectForNativeVariant(UnsafeMethods.ConvertVariantByrefToPtr(ref this));
- }
-
- set
- {
- Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
- if (value != null)
- {
- UnsafeMethods.InitVariantForObject(value, ref this);
- }
- }
- }
-
- public void SetAsByrefVariant(ref Variant value)
- {
- SetAsByref(ref value, VarEnum.VT_VARIANT);
- }
-
- // constructs a ByRef variant to pass contents of another variant ByRef.
- public unsafe void SetAsByrefVariantIndirect(ref Variant value)
- {
- Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
- Debug.Assert((value.VariantType & VarEnum.VT_BYREF) == 0, "double indirection");
-
- switch (value.VariantType)
- {
- case VarEnum.VT_EMPTY:
- case VarEnum.VT_NULL:
- // these cannot combine with VT_BYREF. Should try passing as a variant reference
- SetAsByrefVariant(ref value);
- return;
- case VarEnum.VT_RECORD:
- // VT_RECORD's are weird in that regardless of is the VT_BYREF flag is set or not
- // they have the same internal representation.
- _typeUnion._unionTypes._record = value._typeUnion._unionTypes._record;
- break;
- case VarEnum.VT_DECIMAL:
- _typeUnion._unionTypes._byref = (IntPtr)Unsafe.AsPointer(ref value._decimal);
- break;
- default:
- _typeUnion._unionTypes._byref = (IntPtr)Unsafe.AsPointer(ref value._typeUnion._unionTypes._byref);
- break;
- }
- VariantType = (value.VariantType | VarEnum.VT_BYREF);
- }
-
- private unsafe void SetAsByref(ref T value, VarEnum type)
- {
- Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
- VariantType = type | VarEnum.VT_BYREF;
- _typeUnion._unionTypes._byref = (IntPtr)Unsafe.AsPointer(ref value);
- }
-
- internal static System.Reflection.PropertyInfo GetAccessor(VarEnum varType)
- {
- switch (varType)
- {
- case VarEnum.VT_I1: return typeof(Variant).GetProperty(nameof(AsI1));
- case VarEnum.VT_I2: return typeof(Variant).GetProperty(nameof(AsI2));
- case VarEnum.VT_I4: return typeof(Variant).GetProperty(nameof(AsI4));
- case VarEnum.VT_I8: return typeof(Variant).GetProperty(nameof(AsI8));
- case VarEnum.VT_UI1: return typeof(Variant).GetProperty(nameof(AsUi1));
- case VarEnum.VT_UI2: return typeof(Variant).GetProperty(nameof(AsUi2));
- case VarEnum.VT_UI4: return typeof(Variant).GetProperty(nameof(AsUi4));
- case VarEnum.VT_UI8: return typeof(Variant).GetProperty(nameof(AsUi8));
- case VarEnum.VT_INT: return typeof(Variant).GetProperty(nameof(AsInt));
- case VarEnum.VT_UINT: return typeof(Variant).GetProperty(nameof(AsUint));
- case VarEnum.VT_BOOL: return typeof(Variant).GetProperty(nameof(AsBool));
- case VarEnum.VT_ERROR: return typeof(Variant).GetProperty(nameof(AsError));
- case VarEnum.VT_R4: return typeof(Variant).GetProperty(nameof(AsR4));
- case VarEnum.VT_R8: return typeof(Variant).GetProperty(nameof(AsR8));
- case VarEnum.VT_DECIMAL: return typeof(Variant).GetProperty(nameof(AsDecimal));
- case VarEnum.VT_CY: return typeof(Variant).GetProperty(nameof(AsCy));
- case VarEnum.VT_DATE: return typeof(Variant).GetProperty(nameof(AsDate));
- case VarEnum.VT_BSTR: return typeof(Variant).GetProperty(nameof(AsBstr));
- case VarEnum.VT_UNKNOWN: return typeof(Variant).GetProperty(nameof(AsUnknown));
- case VarEnum.VT_DISPATCH: return typeof(Variant).GetProperty(nameof(AsDispatch));
-
- case VarEnum.VT_VARIANT:
- case VarEnum.VT_RECORD:
- case VarEnum.VT_ARRAY:
- return typeof(Variant).GetProperty(nameof(AsVariant));
-
- default:
- throw new NotSupportedException();
- }
- }
-
- internal static System.Reflection.MethodInfo GetByrefSetter(VarEnum varType)
- {
- switch (varType)
- {
- case VarEnum.VT_I1: return typeof(Variant).GetMethod(nameof(SetAsByrefI1));
- case VarEnum.VT_I2: return typeof(Variant).GetMethod(nameof(SetAsByrefI2));
- case VarEnum.VT_I4: return typeof(Variant).GetMethod(nameof(SetAsByrefI4));
- case VarEnum.VT_I8: return typeof(Variant).GetMethod(nameof(SetAsByrefI8));
- case VarEnum.VT_UI1: return typeof(Variant).GetMethod(nameof(SetAsByrefUi1));
- case VarEnum.VT_UI2: return typeof(Variant).GetMethod(nameof(SetAsByrefUi2));
- case VarEnum.VT_UI4: return typeof(Variant).GetMethod(nameof(SetAsByrefUi4));
- case VarEnum.VT_UI8: return typeof(Variant).GetMethod(nameof(SetAsByrefUi8));
- case VarEnum.VT_INT: return typeof(Variant).GetMethod(nameof(SetAsByrefInt));
- case VarEnum.VT_UINT: return typeof(Variant).GetMethod(nameof(SetAsByrefUint));
- case VarEnum.VT_BOOL: return typeof(Variant).GetMethod(nameof(SetAsByrefBool));
- case VarEnum.VT_ERROR: return typeof(Variant).GetMethod(nameof(SetAsByrefError));
- case VarEnum.VT_R4: return typeof(Variant).GetMethod(nameof(SetAsByrefR4));
- case VarEnum.VT_R8: return typeof(Variant).GetMethod(nameof(SetAsByrefR8));
- case VarEnum.VT_DECIMAL: return typeof(Variant).GetMethod(nameof(SetAsByrefDecimal));
- case VarEnum.VT_CY: return typeof(Variant).GetMethod(nameof(SetAsByrefCy));
- case VarEnum.VT_DATE: return typeof(Variant).GetMethod(nameof(SetAsByrefDate));
- case VarEnum.VT_BSTR: return typeof(Variant).GetMethod(nameof(SetAsByrefBstr));
- case VarEnum.VT_UNKNOWN: return typeof(Variant).GetMethod(nameof(SetAsByrefUnknown));
- case VarEnum.VT_DISPATCH: return typeof(Variant).GetMethod(nameof(SetAsByrefDispatch));
-
- case VarEnum.VT_VARIANT:
- return typeof(Variant).GetMethod(nameof(SetAsByrefVariant));
- case VarEnum.VT_RECORD:
- case VarEnum.VT_ARRAY:
- return typeof(Variant).GetMethod(nameof(SetAsByrefVariantIndirect));
-
- default:
- throw new NotSupportedException();
- }
- }
-
- public override string ToString() => $"Variant ({VariantType})";
-
- public void SetAsIConvertible(IConvertible value)
- {
- Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
-
- TypeCode tc = value.GetTypeCode();
- CultureInfo ci = CultureInfo.CurrentCulture;
-
- switch (tc)
- {
- case TypeCode.Empty: break;
- case TypeCode.Object: AsUnknown = value; break;
- case TypeCode.DBNull: SetAsNULL(); break;
- case TypeCode.Boolean: AsBool = value.ToBoolean(ci); break;
- case TypeCode.Char: AsUi2 = value.ToChar(ci); break;
- case TypeCode.SByte: AsI1 = value.ToSByte(ci); break;
- case TypeCode.Byte: AsUi1 = value.ToByte(ci); break;
- case TypeCode.Int16: AsI2 = value.ToInt16(ci); break;
- case TypeCode.UInt16: AsUi2 = value.ToUInt16(ci); break;
- case TypeCode.Int32: AsI4 = value.ToInt32(ci); break;
- case TypeCode.UInt32: AsUi4 = value.ToUInt32(ci); break;
- case TypeCode.Int64: AsI8 = value.ToInt64(ci); break;
- case TypeCode.UInt64: AsI8 = value.ToInt64(ci); break;
- case TypeCode.Single: AsR4 = value.ToSingle(ci); break;
- case TypeCode.Double: AsR8 = value.ToDouble(ci); break;
- case TypeCode.Decimal: AsDecimal = value.ToDecimal(ci); break;
- case TypeCode.DateTime: AsDate = value.ToDateTime(ci); break;
- case TypeCode.String: AsBstr = value.ToString(ci); break;
-
- default:
- throw new NotSupportedException();
- }
- }
- }
-}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
index 37e34303feadff..559b9e92c01b1e 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
@@ -10,31 +10,32 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
{
[StructLayout(LayoutKind.Sequential)]
internal struct VariantArray1
{
- public Variant Element0;
+ public ComVariant Element0;
}
[StructLayout(LayoutKind.Sequential)]
internal struct VariantArray2
{
- public Variant Element0, Element1;
+ public ComVariant Element0, Element1;
}
[StructLayout(LayoutKind.Sequential)]
internal struct VariantArray4
{
- public Variant Element0, Element1, Element2, Element3;
+ public ComVariant Element0, Element1, Element2, Element3;
}
[StructLayout(LayoutKind.Sequential)]
internal struct VariantArray8
{
- public Variant Element0, Element1, Element2, Element3, Element4, Element5, Element6, Element7;
+ public ComVariant Element0, Element1, Element2, Element3, Element4, Element5, Element6, Element7;
}
//
@@ -49,7 +50,6 @@ internal static class VariantArray
// Don't need a dictionary for this, it will have very few elements
// (guaranteed less than 28, in practice 0-2)
private static readonly List s_generatedTypes = new List(0);
- private static readonly string[] s_genericTName = new string[] { "T" };
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray1))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray2))]
@@ -62,8 +62,6 @@ internal static MemberExpression GetStructField(ParameterExpression variantArray
return Expression.Field(variantArray, "Element" + field);
}
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern",
- Justification = "MakeGenericType is called on a dynamically created type that doesn't contain trimming annotations.")]
internal static Type GetStructType(int args)
{
Debug.Assert(args >= 0);
@@ -91,7 +89,7 @@ internal static Type GetStructType(int args)
}
// Else generate a new type
- Type type = CreateCustomType(size).MakeGenericType(new Type[] { typeof(Variant) });
+ Type type = CreateCustomType(size);
s_generatedTypes.Add(type);
return type;
}
@@ -101,10 +99,9 @@ private static Type CreateCustomType(int size)
{
TypeAttributes attrs = TypeAttributes.NotPublic | TypeAttributes.SequentialLayout;
TypeBuilder type = UnsafeMethods.DynamicModule.DefineType("VariantArray" + size, attrs, typeof(ValueType));
- GenericTypeParameterBuilder T = type.DefineGenericParameters(s_genericTName)[0];
for (int i = 0; i < size; i++)
{
- type.DefineField("Element" + i, T, FieldAttributes.Public);
+ type.DefineField("Element" + i, typeof(ComVariant), FieldAttributes.Public);
}
return type.CreateType();
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
index 4fdb65bbd1aefb..39bdcc24d96478 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
@@ -4,12 +4,14 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
+using System.Reflection;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
{
///
- /// VariantBuilder handles packaging of arguments into a Variant for a call to IDispatch.Invoke
+ /// VariantBuilder handles packaging of arguments into an ComVariant for a call to IDispatch.Invoke
///
internal sealed class VariantBuilder
{
@@ -49,8 +51,8 @@ internal Expression InitializeArgumentVariant(MemberExpression variant, Expressi
return Expression.Block(
Expression.Assign(TempVariable, argExpr),
Expression.Call(
+ DynamicVariantExtensions.GetByrefSetter(_targetComType & ~VarEnum.VT_BYREF),
variant,
- Variant.GetByrefSetter(_targetComType & ~VarEnum.VT_BYREF),
TempVariable
)
);
@@ -63,13 +65,13 @@ internal Expression InitializeArgumentVariant(MemberExpression variant, Expressi
if (_argBuilder is ConvertibleArgBuilder)
{
return Expression.Call(
+ typeof(DynamicVariantExtensions).GetMethod(nameof(DynamicVariantExtensions.SetAsIConvertible)),
variant,
- typeof(Variant).GetMethod(nameof(Variant.SetAsIConvertible)),
argument
);
}
- if (Variant.IsPrimitiveType(_targetComType) ||
+ if (_targetComType.IsPrimitiveType() ||
(_targetComType == VarEnum.VT_DISPATCH) ||
(_targetComType == VarEnum.VT_UNKNOWN) ||
(_targetComType == VarEnum.VT_VARIANT) ||
@@ -77,13 +79,10 @@ internal Expression InitializeArgumentVariant(MemberExpression variant, Expressi
(_targetComType == VarEnum.VT_ARRAY))
{
// paramVariants._elementN.AsT = (cast)argN
- return Expression.Assign(
- Expression.Property(
- variant,
- Variant.GetAccessor(_targetComType)
- ),
- argument
- );
+ return Expression.Call(null,
+ DynamicVariantExtensions.GetSetter(_targetComType),
+ variant,
+ argument);
}
switch (_targetComType)
@@ -92,8 +91,8 @@ internal Expression InitializeArgumentVariant(MemberExpression variant, Expressi
return null;
case VarEnum.VT_NULL:
- // paramVariants._elementN.SetAsNull();
- return Expression.Call(variant, typeof(Variant).GetMethod(nameof(Variant.SetAsNULL)));
+ // paramVariants._elementN = ComVariant.Null;
+ return Expression.Assign(variant, Expression.Property(null, typeof(ComVariant).GetProperty(nameof(ComVariant.Null), BindingFlags.Public | BindingFlags.Static)));
default:
Debug.Assert(false, "Unexpected VarEnum");
@@ -131,7 +130,7 @@ internal Expression Clear()
if (_argBuilder is VariantArgBuilder)
{
Debug.Assert(TempVariable != null);
- return Expression.Call(TempVariable, typeof(Variant).GetMethod(nameof(Variant.Clear)));
+ return Expression.Call(TempVariable, typeof(ComVariant).GetMethod(nameof(ComVariant.Dispose)));
}
return null;
}
@@ -148,11 +147,11 @@ internal Expression Clear()
case VarEnum.VT_ARRAY:
case VarEnum.VT_RECORD:
case VarEnum.VT_VARIANT:
- // paramVariants._elementN.Clear()
- return Expression.Call(_variant, typeof(Variant).GetMethod(nameof(Variant.Clear)));
+ // paramVariants._elementN.Dispose()
+ return Expression.Call(_variant, typeof(ComVariant).GetMethod(nameof(ComVariant.Dispose)));
default:
- Debug.Assert(Variant.IsPrimitiveType(_targetComType), "Unexpected VarEnum");
+ Debug.Assert(_targetComType.IsPrimitiveType(), "Unexpected VarEnum");
return null;
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs
index cd03e816fb6568..bf74d11775dcfe 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs
@@ -284,7 +284,6 @@ public void AddEnvironmentVariablesUsingPrefixWithDoubleUnderscores_Bind_PrefixM
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void BindingDoesNotThrowIfReloadedDuringBinding()
{
var dic = new Dictionary
diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
index cc5a7df5421417..ced9dd64c3007a 100644
--- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
@@ -286,7 +286,6 @@ public void LoadAndCombineKeyValuePairsFromDifferentConfigurationProvidersWithAb
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void CanOverrideValuesWithNewConfigurationProvider()
{
WriteTestFiles();
@@ -941,7 +940,6 @@ await WaitForChange(
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void BindingDoesNotThrowIfReloadedDuringBinding()
{
WriteTestFiles();
diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs
index fee56f79fb003e..3982ae29846862 100644
--- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs
+++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs
@@ -279,7 +279,6 @@ public void ApplicationNameSetFromArgument()
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void NoSpecialEntryPointPatternCanRunInParallel()
{
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(NoSpecialEntryPointPattern.Program).Assembly, s_WaitTimeout);
diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs
index fab5ad4fc1fdc9..f537d8ca617f6f 100644
--- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs
+++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs
@@ -1204,7 +1204,6 @@ public async Task AddHttpClient_MessageHandler_Scope_TransientDependency()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported), nameof(PlatformDetection.IsReflectionEmitSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddHttpClient_GetAwaiterAndResult_InSingleThreadedSynchronizationContext_ShouldNotHangs()
{
// Arrange
@@ -1368,7 +1367,6 @@ public void SuppressScope_True_InScope_DoesNotCreateScope()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91673", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddHttpClient_ConfigurePrimaryHttpMessageHandler_ApplyChangesPrimaryHandler()
{
// Arrange
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs
index 573006673d8889..6da081c4e86ab0 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs
@@ -74,7 +74,6 @@ internal static (ConsoleLogger Logger, ConsoleSink Sink, ConsoleSink ErrorSink,
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded()
{
// Arrange
@@ -88,7 +87,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatterNames))]
public void InvalidLogLevel_Throws(string formatterName)
{
@@ -103,7 +101,6 @@ public void InvalidLogLevel_Throws(string formatterName)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatterNamesAndLevels))]
public void NoMessageOrException_Noop(string formatterName, LogLevel level)
{
@@ -123,7 +120,6 @@ public void NoMessageOrException_Noop(string formatterName, LogLevel level)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatterNamesAndLevels))]
public void Log_LogsCorrectTimestamp(string formatterName, LogLevel level)
{
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs
index 945f00905c8e36..99b49170ed8e1d 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs
@@ -76,7 +76,6 @@ public void AddConsoleFormatter_NullConfigure_Throws()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatterNames))]
public void AddConsole_ConsoleLoggerOptionsFromConfigFile_IsReadFromLoggingConfiguration(string formatterName)
{
@@ -156,7 +155,6 @@ private class CustomOptions : ConsoleFormatterOptions
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddSimpleConsole_ChangeProperties_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -187,7 +185,6 @@ public void AddSimpleConsole_ChangeProperties_IsReadFromLoggingConfiguration()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddSimpleConsole_OutsideConfig_TakesProperty()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -218,7 +215,6 @@ public void AddSimpleConsole_OutsideConfig_TakesProperty()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddSystemdConsole_ChangeProperties_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -245,7 +241,6 @@ public void AddSystemdConsole_ChangeProperties_IsReadFromLoggingConfiguration()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddSystemdConsole_OutsideConfig_TakesProperty()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -276,7 +271,6 @@ public void AddSystemdConsole_OutsideConfig_TakesProperty()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddJsonConsole_ChangeProperties_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -305,7 +299,6 @@ public void AddJsonConsole_ChangeProperties_IsReadFromLoggingConfiguration()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddJsonConsole_OutsideConfig_TakesProperty()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -340,7 +333,6 @@ public void AddJsonConsole_OutsideConfig_TakesProperty()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddConsole_NullFormatterNameUsingSystemdFormat_AnyDeprecatedPropertiesOverwriteFormatterOptions()
{
var configs = new[] {
@@ -386,7 +378,6 @@ public void AddConsole_MaxQueueLengthSetToNegativeOrZero_Throws(int invalidMaxQu
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddConsole_MaxQueueLengthLargerThanZero_ConfiguredProperly()
{
var configs = new[] {
@@ -408,7 +399,6 @@ public void AddConsole_MaxQueueLengthLargerThanZero_ConfiguredProperly()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddConsole_NullFormatterName_UsingSystemdFormat_IgnoreFormatterOptionsAndUseDeprecatedInstead()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -441,7 +431,6 @@ public void AddConsole_NullFormatterName_UsingSystemdFormat_IgnoreFormatterOptio
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void AddConsole_NullFormatterName_UsingDefaultFormat_IgnoreFormatterOptionsAndUseDeprecatedInstead()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] {
@@ -481,7 +470,6 @@ public void AddConsole_NullFormatterName_UsingDefaultFormat_IgnoreFormatterOptio
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData("missingFormatter")]
[InlineData("simple")]
[InlineData("Simple")]
@@ -525,7 +513,6 @@ public void AddConsole_FormatterNameIsSet_UsingDefaultFormat_IgnoreDeprecatedAnd
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData("missingFormatter")]
[InlineData("systemd")]
[InlineData("Systemd")]
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerProcessorTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerProcessorTests.cs
index 618d4cc9fb84f7..dfc7eaae8fe24c 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerProcessorTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerProcessorTests.cs
@@ -15,7 +15,6 @@ public class ConsoleLoggerProcessorTests
private const string _loggerName = "test";
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void LogAfterDisposeWritesLog()
{
// Arrange
@@ -64,7 +63,6 @@ public void LogsFlushedAfterDispose()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData(-1)]
[InlineData(0)]
public static void MaxQueueLength_SetInvalid_Throws(int invalidMaxQueueLength)
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
index f0ef3d6cd7e1d1..0994980590122b 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
@@ -174,7 +174,6 @@ internal static string GetJsonLogLevelString(LogLevel logLevel)
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void LogsWhenMessageIsNotProvided()
{
// Arrange
@@ -207,7 +206,6 @@ public void LogsWhenMessageIsNotProvided()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void DoesNotLog_NewLine_WhenNoExceptionIsProvided()
{
// Arrange
@@ -236,7 +234,6 @@ public void DoesNotLog_NewLine_WhenNoExceptionIsProvided()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData(null, 0)]
[InlineData(null, 1)]
[InlineData("missingFormatter", 0)]
@@ -279,7 +276,6 @@ public void Options_FormatterNameNull_UsesDeprecatedProperties(string formatterN
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData("Route with name 'Simple' was not found.")]
public void Writes_NewLine_WhenExceptionIsProvided(string message)
{
@@ -304,7 +300,6 @@ public void Writes_NewLine_WhenExceptionIsProvided(string message)
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ThrowsException_WhenNoFormatterIsProvided()
{
// Arrange
@@ -316,7 +311,6 @@ public void ThrowsException_WhenNoFormatterIsProvided()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void LogsWhenNullFilterGiven()
{
// Arrange
@@ -338,7 +332,6 @@ public void LogsWhenNullFilterGiven()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteCritical_LogsCorrectColors()
{
// Arrange
@@ -360,7 +353,6 @@ public void WriteCritical_LogsCorrectColors()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteError_LogsCorrectColors()
{
// Arrange
@@ -382,7 +374,6 @@ public void WriteError_LogsCorrectColors()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteWarning_LogsCorrectColors()
{
// Arrange
@@ -404,7 +395,6 @@ public void WriteWarning_LogsCorrectColors()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteInformation_LogsCorrectColors()
{
// Arrange
@@ -456,7 +446,6 @@ public void AddConsole_IsOutputRedirected_ColorDisabled()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteDebug_LogsCorrectColors()
{
// Arrange
@@ -478,7 +467,6 @@ public void WriteDebug_LogsCorrectColors()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteTrace_LogsCorrectColors()
{
// Arrange
@@ -500,7 +488,6 @@ public void WriteTrace_LogsCorrectColors()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WriteAllLevelsDisabledColors_LogsNoColors()
{
// Arrange
@@ -525,7 +512,6 @@ public void WriteAllLevelsDisabledColors_LogsNoColors()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void Log_LogsCorrectTimestamp(ConsoleLoggerFormat format, LogLevel level)
{
@@ -567,7 +553,6 @@ public void Log_LogsCorrectTimestamp(ConsoleLoggerFormat format, LogLevel level)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void WriteCore_LogsCorrectTimestampInUtc(ConsoleLoggerFormat format, LogLevel level)
{
@@ -609,7 +594,6 @@ public void WriteCore_LogsCorrectTimestampInUtc(ConsoleLoggerFormat format, LogL
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void WriteCore_LogsCorrectMessages(ConsoleLoggerFormat format, LogLevel level)
{
@@ -654,7 +638,6 @@ public void WriteCore_LogsCorrectMessages(ConsoleLoggerFormat format, LogLevel l
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void NoLogScope_DoesNotWriteAnyScopeContentToOutput()
{
// Arrange
@@ -676,7 +659,6 @@ public void NoLogScope_DoesNotWriteAnyScopeContentToOutput()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void WritingScopes_LogsWithCorrectColors()
{
// Arrange
@@ -703,7 +685,6 @@ public void WritingScopes_LogsWithCorrectColors()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Formats))]
public void WritingScopes_LogsExpectedMessage(ConsoleLoggerFormat format)
{
@@ -755,7 +736,6 @@ public void WritingScopes_LogsExpectedMessage(ConsoleLoggerFormat format)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Formats))]
public void WritingNestedScope_LogsNullScopeName(ConsoleLoggerFormat format)
{
@@ -805,7 +785,6 @@ public void WritingNestedScope_LogsNullScopeName(ConsoleLoggerFormat format)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Formats))]
public void WritingNestedScopes_LogsExpectedMessage(ConsoleLoggerFormat format)
{
@@ -864,7 +843,6 @@ public void WritingNestedScopes_LogsExpectedMessage(ConsoleLoggerFormat format)
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Formats))]
public void WritingMultipleScopes_LogsExpectedMessage(ConsoleLoggerFormat format)
{
@@ -934,7 +912,6 @@ public void WritingMultipleScopes_LogsExpectedMessage(ConsoleLoggerFormat format
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void CallingBeginScopeOnLogger_AlwaysReturnsNewDisposableInstance()
{
// Arrange
@@ -953,7 +930,6 @@ public void CallingBeginScopeOnLogger_AlwaysReturnsNewDisposableInstance()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void CallingBeginScopeOnLogger_ReturnsNonNullableInstance()
{
// Arrange
@@ -969,7 +945,6 @@ public void CallingBeginScopeOnLogger_ReturnsNonNullableInstance()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Formats))]
public void ConsoleLoggerLogsToError_WhenOverErrorLevel(ConsoleLoggerFormat format)
{
@@ -1020,7 +995,6 @@ public void ConsoleLoggerLogsToError_WhenOverErrorLevel(ConsoleLoggerFormat form
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void WriteCore_NullMessageWithException(ConsoleLoggerFormat format, LogLevel level)
{
@@ -1065,7 +1039,6 @@ public void WriteCore_NullMessageWithException(ConsoleLoggerFormat format, LogLe
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void WriteCore_EmptyMessageWithException(ConsoleLoggerFormat format, LogLevel level)
{
@@ -1109,7 +1082,6 @@ public void WriteCore_EmptyMessageWithException(ConsoleLoggerFormat format, LogL
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FormatsAndLevels))]
public void WriteCore_MessageWithNullException(ConsoleLoggerFormat format, LogLevel level)
{
@@ -1150,7 +1122,6 @@ public void WriteCore_MessageWithNullException(ConsoleLoggerFormat format, LogLe
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(Levels))]
public void WriteCore_NullMessageWithNullException(LogLevel level)
{
@@ -1169,7 +1140,6 @@ public void WriteCore_NullMessageWithNullException(LogLevel level)
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public static void IsEnabledReturnsCorrectValue()
{
var logger = SetUp().Logger;
@@ -1184,7 +1154,6 @@ public static void IsEnabledReturnsCorrectValue()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_DisableColors_IsAppliedToLoggers()
{
// Arrange
@@ -1219,7 +1188,6 @@ public void ConsoleLoggerOptions_SetInvalidBufferMode_Throws()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_DisableColors_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:DisableColors", "true") }).Build();
@@ -1237,7 +1205,6 @@ public void ConsoleLoggerOptions_DisableColors_IsReadFromLoggingConfiguration()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded()
{
// Arrange
@@ -1252,7 +1219,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_TimeStampFormat_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:TimeStampFormat", "yyyyMMddHHmmss") }).Build();
@@ -1270,7 +1236,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReadFromLoggingConfiguration(
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_TimeStampFormat_MultipleReloads()
{
var monitor = new TestOptionsMonitor(new ConsoleLoggerOptions());
@@ -1285,7 +1250,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_MultipleReloads()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_IncludeScopes_IsAppliedToLoggers()
{
// Arrange
@@ -1300,7 +1264,6 @@ public void ConsoleLoggerOptions_IncludeScopes_IsAppliedToLoggers()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_LogAsErrorLevel_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:LogToStandardErrorThreshold", "Warning") }).Build();
@@ -1318,7 +1281,6 @@ public void ConsoleLoggerOptions_LogAsErrorLevel_IsReadFromLoggingConfiguration(
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_LogAsErrorLevel_IsAppliedToLoggers()
{
// Arrange
@@ -1333,7 +1295,6 @@ public void ConsoleLoggerOptions_LogAsErrorLevel_IsAppliedToLoggers()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_UpdateQueueOptions_UpdatesConsoleLoggerProcessorProperties()
{
// Arrange
@@ -1353,7 +1314,6 @@ public void ConsoleLoggerOptions_UpdateQueueOptions_UpdatesConsoleLoggerProcesso
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_UseUtcTimestamp_IsAppliedToLoggers()
{
// Arrange
@@ -1368,7 +1328,6 @@ public void ConsoleLoggerOptions_UseUtcTimestamp_IsAppliedToLoggers()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void ConsoleLoggerOptions_IncludeScopes_IsReadFromLoggingConfiguration()
{
var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:IncludeScopes", "true") }).Build();
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/JsonConsoleFormatterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/JsonConsoleFormatterTests.cs
index 153ba5503eeb47..0ef491abbc1723 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/JsonConsoleFormatterTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/JsonConsoleFormatterTests.cs
@@ -18,7 +18,6 @@ namespace Microsoft.Extensions.Logging.Console.Test
public class JsonConsoleFormatterTests : ConsoleFormatterTests
{
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void NoLogScope_DoesNotWriteAnyScopeContentToOutput_Json()
{
// Arrange
@@ -80,7 +79,6 @@ public void Log_TimestampFormatSet_ContainsTimestamp()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_NullMessage_LogsWhenMessageIsNotProvided()
{
// Arrange
@@ -125,7 +123,6 @@ public void Log_NullMessage_LogsWhenMessageIsNotProvided()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_ExceptionWithMessage_ExtractsInfo()
{
// Arrange
@@ -180,7 +177,6 @@ public void Log_ExceptionWithMessage_ExtractsInfo()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_IncludeScopes_ContainsDuplicateNamedPropertiesInScope_AcceptableJson()
{
// Arrange
@@ -214,7 +210,6 @@ public void Log_IncludeScopes_ContainsDuplicateNamedPropertiesInScope_Acceptable
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_StateAndScopeAreCollections_IncludesMessageAndCollectionValues()
{
// Arrange
@@ -250,7 +245,6 @@ public void Log_StateAndScopeAreCollections_IncludesMessageAndCollectionValues()
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(SpecialCaseValues))]
public void Log_StateAndScopeContainsSpecialCaseValue_SerializesValueAsExpected(object value, string expectedJsonValue)
{
@@ -281,7 +275,6 @@ public void Log_StateAndScopeContainsSpecialCaseValue_SerializesValueAsExpected(
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(FloatingPointValues))]
public void Log_StateAndScopeContainsFloatingPointType_SerializesValue(object value)
{
@@ -321,7 +314,6 @@ static void AssertMessageValue(string message, string propertyName)
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_StateAndScopeContainsNullValue_SerializesNull()
{
// Arrange
@@ -351,7 +343,6 @@ public void Log_StateAndScopeContainsNullValue_SerializesNull()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_ScopeIsIEnumerable_SerializesKeyValuePair()
{
// Arrange
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/SimpleConsoleFormatterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/SimpleConsoleFormatterTests.cs
index 26bd40775bb371..3bb1fa491ecea0 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/SimpleConsoleFormatterTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/SimpleConsoleFormatterTests.cs
@@ -10,7 +10,6 @@ namespace Microsoft.Extensions.Logging.Console.Test
public class SimpleConsoleFormatterTests : ConsoleFormatterTests
{
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[InlineData(LoggerColorBehavior.Default)]
[InlineData(LoggerColorBehavior.Enabled)]
[InlineData(LoggerColorBehavior.Disabled)]
@@ -55,7 +54,6 @@ public void Log_WritingScopes_LogsWithCorrectColorsWhenColorEnabled(LoggerColorB
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_NoLogScope_DoesNotWriteAnyScopeContentToOutput()
{
// Arrange
@@ -111,7 +109,6 @@ public void Log_SingleLine_LogsWhenMessageIsNotProvided()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void Log_SingleLine_LogsWhenBothMessageAndExceptionProvided()
{
// Arrange
diff --git a/src/libraries/System.Collections.NonGeneric/tests/QueueTests.cs b/src/libraries/System.Collections.NonGeneric/tests/QueueTests.cs
index 69a09d473bedc1..56b509470e8224 100644
--- a/src/libraries/System.Collections.NonGeneric/tests/QueueTests.cs
+++ b/src/libraries/System.Collections.NonGeneric/tests/QueueTests.cs
@@ -913,7 +913,6 @@ public static void Synchronized()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void SynchronizedEnqueue()
{
// Enqueue
diff --git a/src/libraries/System.Collections/ref/System.Collections.cs b/src/libraries/System.Collections/ref/System.Collections.cs
index b0272046b38412..c12b04c3a3cf07 100644
--- a/src/libraries/System.Collections/ref/System.Collections.cs
+++ b/src/libraries/System.Collections/ref/System.Collections.cs
@@ -126,6 +126,7 @@ public void EnqueueRange(System.Collections.Generic.IEnumerable<(TElement Elemen
public void EnqueueRange(System.Collections.Generic.IEnumerable elements, TPriority priority) { }
public int EnsureCapacity(int capacity) { throw null; }
public TElement Peek() { throw null; }
+ public bool Remove(TElement element, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TElement removedElement, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TPriority priority, System.Collections.Generic.IEqualityComparer? equalityComparer = null) { throw null; }
public void TrimExcess() { }
public bool TryDequeue([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TElement element, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TPriority priority) { throw null; }
public bool TryPeek([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TElement element, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TPriority priority) { throw null; }
diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
index e8d8221641cd2a..edc1327b446cab 100644
--- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
+++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
@@ -502,6 +502,59 @@ public void EnqueueRange(IEnumerable elements, TPriority priority)
}
}
+ ///
+ /// Removes the first occurrence that equals the specified parameter.
+ ///
+ /// The element to try to remove.
+ /// The actual element that got removed from the queue.
+ /// The priority value associated with the removed element.
+ /// The equality comparer governing element equality.
+ /// if matching entry was found and removed, otherwise.
+ ///
+ /// The method performs a linear-time scan of every element in the heap, removing the first value found to match the parameter.
+ /// In case of duplicate entries, what entry does get removed is non-deterministic and does not take priority into account.
+ ///
+ /// If no is specified, will be used instead.
+ ///
+ public bool Remove(
+ TElement element,
+ [MaybeNullWhen(false)] out TElement removedElement,
+ [MaybeNullWhen(false)] out TPriority priority,
+ IEqualityComparer? equalityComparer = null)
+ {
+ int index = FindIndex(element, equalityComparer);
+ if (index < 0)
+ {
+ removedElement = default;
+ priority = default;
+ return false;
+ }
+
+ (TElement Element, TPriority Priority)[] nodes = _nodes;
+ (removedElement, priority) = nodes[index];
+ int newSize = --_size;
+
+ if (index < newSize)
+ {
+ // We're removing an element from the middle of the heap.
+ // Pop the last element in the collection and sift downward from the removed index.
+ (TElement Element, TPriority Priority) lastNode = nodes[newSize];
+
+ if (_comparer == null)
+ {
+ MoveDownDefaultComparer(lastNode, index);
+ }
+ else
+ {
+ MoveDownCustomComparer(lastNode, index);
+ }
+ }
+
+ nodes[newSize] = default;
+ _version++;
+ return true;
+ }
+
///
/// Removes all items from the .
///
@@ -809,6 +862,41 @@ private void MoveDownCustomComparer((TElement Element, TPriority Priority) node,
nodes[nodeIndex] = node;
}
+ ///
+ /// Scans the heap for the first index containing an element equal to the specified parameter.
+ ///
+ private int FindIndex(TElement element, IEqualityComparer? equalityComparer)
+ {
+ equalityComparer ??= EqualityComparer.Default;
+ ReadOnlySpan<(TElement Element, TPriority Priority)> nodes = _nodes.AsSpan(0, _size);
+
+ // Currently the JIT doesn't optimize direct EqualityComparer.Default.Equals
+ // calls for reference types, so we want to cache the comparer instance instead.
+ // TODO https://github.com/dotnet/runtime/issues/10050: Update if this changes in the future.
+ if (typeof(TElement).IsValueType && equalityComparer == EqualityComparer.Default)
+ {
+ for (int i = 0; i < nodes.Length; i++)
+ {
+ if (EqualityComparer.Default.Equals(element, nodes[i].Element))
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < nodes.Length; i++)
+ {
+ if (equalityComparer.Equals(element, nodes[i].Element))
+ {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ }
+
///
/// Initializes the custom comparer to be used internally by the heap.
///
diff --git a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.Tests.cs
index c50dfa977d045a..0f50f9183f5cbe 100644
--- a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.Tests.cs
+++ b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.Tests.cs
@@ -93,7 +93,7 @@ public void PriorityQueue_EnumerableConstructor_ShouldContainAllElements(int cou
#endregion
- #region Enqueue, Dequeue, Peek, EnqueueDequeue, DequeueEnqueue
+ #region Enqueue, Dequeue, Peek, EnqueueDequeue, DequeueEnqueue, Remove
[Theory]
[MemberData(nameof(ValidCollectionSizes))]
@@ -246,6 +246,35 @@ public void PriorityQueue_DequeueEnqueue(int count)
AssertExtensions.CollectionEqual(expectedItems, queue.UnorderedItems, EqualityComparer<(TElement, TPriority)>.Default);
}
+ [Theory]
+ [MemberData(nameof(ValidCollectionSizes))]
+ public void PriorityQueue_Remove_AllElements(int count)
+ {
+ bool result;
+ TElement removedElement;
+ TPriority removedPriority;
+
+ PriorityQueue queue = CreatePriorityQueue(count, count, out List<(TElement element, TPriority priority)> generatedItems);
+
+ for (int i = count - 1; i >= 0; i--)
+ {
+ (TElement element, TPriority priority) = generatedItems[i];
+
+ result = queue.Remove(element, out removedElement, out removedPriority);
+
+ Assert.True(result);
+ Assert.Equal(element, removedElement);
+ Assert.Equal(priority, removedPriority);
+ Assert.Equal(i, queue.Count);
+ }
+
+ result = queue.Remove(default, out removedElement, out removedPriority);
+
+ Assert.False(result);
+ Assert.Equal(default, removedElement);
+ Assert.Equal(default, removedPriority);
+ }
+
#endregion
#region Clear
diff --git a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.Dijkstra.cs b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.Dijkstra.cs
new file mode 100644
index 00000000000000..08155e493ee664
--- /dev/null
+++ b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.Dijkstra.cs
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Linq;
+using Xunit;
+using NodeId = int;
+using Distance = int;
+
+namespace System.Collections.Tests
+{
+ public partial class PriorityQueue_NonGeneric_Tests
+ {
+ public record struct Graph(Edge[][] nodes);
+ public record struct Edge(NodeId neighbor, Distance weight);
+
+ [Fact]
+ public static void PriorityQueue_DijkstraSmokeTest()
+ {
+ var graph = new Graph([
+ [new Edge(1, 7), new Edge(2, 9), new Edge(5, 14)],
+ [new Edge(0, 7), new Edge(2, 10), new Edge(3, 15)],
+ [new Edge(0, 9), new Edge(1, 10), new Edge(3, 11), new Edge(5, 2)],
+ [new Edge(1, 15), new Edge(2, 11), new Edge(4, 6)],
+ [new Edge(3, 6), new Edge(5, 9)],
+ [new Edge(0, 14), new Edge(2, 2), new Edge(4, 9)],
+ ]);
+
+ NodeId startNode = 0;
+
+ (NodeId node, Distance distance)[] expectedDistances =
+ [
+ (0, 0),
+ (1, 7),
+ (2, 9),
+ (3, 20),
+ (4, 20),
+ (5, 11),
+ ];
+
+ (NodeId node, Distance distance)[] actualDistances = RunDijkstra(graph, startNode);
+
+ Assert.Equal(expectedDistances, actualDistances);
+ }
+
+ public static (NodeId node, Distance distance)[] RunDijkstra(Graph graph, NodeId startNode)
+ {
+ Distance[] distances = Enumerable.Repeat(int.MaxValue, graph.nodes.Length).ToArray();
+ var queue = new PriorityQueue();
+
+ distances[startNode] = 0;
+ queue.Enqueue(startNode, 0);
+
+ do
+ {
+ NodeId nodeId = queue.Dequeue();
+ Distance nodeDistance = distances[nodeId];
+
+ foreach (Edge edge in graph.nodes[nodeId])
+ {
+ Distance distance = distances[edge.neighbor];
+ Distance newDistance = nodeDistance + edge.weight;
+ if (newDistance < distance)
+ {
+ distances[edge.neighbor] = newDistance;
+ // Simulate priority update by attempting to remove the entry
+ // before re-inserting it with the new distance.
+ queue.Remove(edge.neighbor, out _, out _);
+ queue.Enqueue(edge.neighbor, newDistance);
+ }
+ }
+ }
+ while (queue.Count > 0);
+
+ return distances.Select((distance, nodeId) => (nodeId, distance)).ToArray();
+ }
+ }
+}
diff --git a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs
index 0bd6a70a8f2a57..03419ab9f6af29 100644
--- a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs
+++ b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs
@@ -8,7 +8,7 @@
namespace System.Collections.Tests
{
- public class PriorityQueue_NonGeneric_Tests : TestBase
+ public partial class PriorityQueue_NonGeneric_Tests : TestBase
{
protected PriorityQueue CreateSmallPriorityQueue(out HashSet<(string, int)> items)
{
@@ -167,6 +167,55 @@ public void PriorityQueue_Generic_EnqueueRange_Null()
Assert.Equal("not null", queue.Dequeue());
}
+ [Fact]
+ public void PriorityQueue_Generic_Remove_MatchingElement()
+ {
+ PriorityQueue queue = new PriorityQueue();
+ queue.EnqueueRange([("value0", 0), ("value1", 1), ("value2", 2)]);
+
+ Assert.True(queue.Remove("value1", out string removedElement, out int removedPriority));
+ Assert.Equal("value1", removedElement);
+ Assert.Equal(1, removedPriority);
+ Assert.Equal(2, queue.Count);
+ }
+
+ [Fact]
+ public void PriorityQueue_Generic_Remove_MismatchElement()
+ {
+ PriorityQueue queue = new PriorityQueue();
+ queue.EnqueueRange([("value0", 0), ("value1", 1), ("value2", 2)]);
+
+ Assert.False(queue.Remove("value4", out string removedElement, out int removedPriority));
+ Assert.Null(removedElement);
+ Assert.Equal(0, removedPriority);
+ Assert.Equal(3, queue.Count);
+ }
+
+ [Fact]
+ public void PriorityQueue_Generic_Remove_DuplicateElement()
+ {
+ PriorityQueue queue = new PriorityQueue();
+ queue.EnqueueRange([("value0", 0), ("value1", 1), ("value0", 2)]);
+
+ Assert.True(queue.Remove("value0", out string removedElement, out int removedPriority));
+ Assert.Equal("value0", removedElement);
+ Assert.True(removedPriority is 0 or 2);
+ Assert.Equal(2, queue.Count);
+ }
+
+ [Fact]
+ public void PriorityQueue_Generic_Remove_CustomEqualityComparer()
+ {
+ PriorityQueue queue = new PriorityQueue();
+ queue.EnqueueRange([("value0", 0), ("value1", 1), ("value2", 2)]);
+ EqualityComparer equalityComparer = EqualityComparer.Create((left, right) => left[^1] == right[^1]);
+
+ Assert.True(queue.Remove("someOtherValue1", out string removedElement, out int removedPriority, equalityComparer));
+ Assert.Equal("value1", removedElement);
+ Assert.Equal(1, removedPriority);
+ Assert.Equal(2, queue.Count);
+ }
+
[Fact]
public void PriorityQueue_Constructor_int_Negative_ThrowsArgumentOutOfRangeException()
{
@@ -207,6 +256,16 @@ public void PriorityQueue_EmptyCollection_Peek_ShouldReturnFalse()
Assert.Throws(() => queue.Peek());
}
+ [Fact]
+ public void PriorityQueue_EmptyCollection_Remove_ShouldReturnFalse()
+ {
+ var queue = new PriorityQueue();
+
+ Assert.False(queue.Remove(element: "element", out string removedElement, out string removedPriority));
+ Assert.Null(removedElement);
+ Assert.Null(removedPriority);
+ }
+
#region EnsureCapacity, TrimExcess
[Fact]
diff --git a/src/libraries/System.Collections/tests/System.Collections.Tests.csproj b/src/libraries/System.Collections/tests/System.Collections.Tests.csproj
index 3d64df4f13ee57..1f45aa68f98f6e 100644
--- a/src/libraries/System.Collections/tests/System.Collections.Tests.csproj
+++ b/src/libraries/System.Collections/tests/System.Collections.Tests.csproj
@@ -1,4 +1,4 @@
-
+
$(NetCoreAppCurrent)
true
@@ -106,6 +106,7 @@
+
diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System.ComponentModel.Composition.Registration.csproj b/src/libraries/System.ComponentModel.Composition.Registration/src/System.ComponentModel.Composition.Registration.csproj
index b8ae87f03d00b9..66378b9fac149a 100644
--- a/src/libraries/System.ComponentModel.Composition.Registration/src/System.ComponentModel.Composition.Registration.csproj
+++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System.ComponentModel.Composition.Registration.csproj
@@ -27,8 +27,8 @@ System.ComponentModel.Composition.Registration.ExportBuilder
-
+
diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/RegistrationBuilder.cs b/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/RegistrationBuilder.cs
index c684ababe674eb..5397b13063aa4a 100644
--- a/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/RegistrationBuilder.cs
+++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/RegistrationBuilder.cs
@@ -20,7 +20,7 @@ internal sealed class InnerRC : ReflectionContext
private static readonly ReflectionContext s_inner = new InnerRC();
private static readonly List s_emptyList = new List();
- private readonly Lock _lock = new Lock();
+ private readonly ReadWriteLock _lock = new ReadWriteLock();
private readonly List _conventions = new List();
private readonly Dictionary> _memberInfos = new Dictionary>();
diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadLock.cs b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadLock.cs
index b60130e6378b5b..40b1dcf7523ee6 100644
--- a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadLock.cs
+++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadLock.cs
@@ -5,10 +5,10 @@ namespace System.Threading
{
internal struct ReadLock : IDisposable
{
- private readonly Lock _lock;
+ private readonly ReadWriteLock _lock;
private int _isDisposed;
- public ReadLock(Lock @lock)
+ public ReadLock(ReadWriteLock @lock)
{
_isDisposed = 0;
_lock = @lock;
diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/Lock.cs b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadWriteLock.cs
similarity index 94%
rename from src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/Lock.cs
rename to src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadWriteLock.cs
index 8d5101922df7ab..6f02e3db4c5546 100644
--- a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/Lock.cs
+++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/ReadWriteLock.cs
@@ -3,7 +3,7 @@
namespace System.Threading
{
- internal sealed class Lock : IDisposable
+ internal sealed class ReadWriteLock : IDisposable
{
private readonly ReaderWriterLockSlim _thisLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private int _isDisposed;
diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/WriteLock.cs b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/WriteLock.cs
index 0c68d24b956dbc..dbd68c6af36e8a 100644
--- a/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/WriteLock.cs
+++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System/Threading/WriteLock.cs
@@ -5,10 +5,10 @@ namespace System.Threading
{
internal struct WriteLock : IDisposable
{
- private readonly Lock _lock;
+ private readonly ReadWriteLock _lock;
private int _isDisposed;
- public WriteLock(Lock @lock)
+ public WriteLock(ReadWriteLock @lock)
{
_isDisposed = 0;
_lock = @lock;
diff --git a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Reader.cs b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Reader.cs
index e7a388afa265a4..77f2a6f3892739 100644
--- a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Reader.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Reader.cs
@@ -8,10 +8,10 @@ namespace Microsoft.Internal
{
internal struct ReadLock : IDisposable
{
- private readonly Lock _lock;
+ private readonly ReadWriteLock _lock;
private int _isDisposed;
- public ReadLock(Lock @lock)
+ public ReadLock(ReadWriteLock @lock)
{
_isDisposed = 0;
_lock = @lock;
diff --git a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.cs b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.ReaderWriter.cs
similarity index 94%
rename from src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.cs
rename to src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.ReaderWriter.cs
index 044b2dc691c32e..d799d56961992d 100644
--- a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.ReaderWriter.cs
@@ -6,7 +6,7 @@
namespace Microsoft.Internal
{
- internal sealed class Lock : IDisposable
+ internal sealed class ReadWriteLock : IDisposable
{
private readonly ReaderWriterLockSlim _thisLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private int _isDisposed;
diff --git a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Writer.cs b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Writer.cs
index a7137c28a379b4..ca6cfd7abb6bb4 100644
--- a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Writer.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Lock.Writer.cs
@@ -8,10 +8,10 @@ namespace Microsoft.Internal
{
internal struct WriteLock : IDisposable
{
- private readonly Lock _lock;
+ private readonly ReadWriteLock _lock;
private int _isDisposed;
- public WriteLock(Lock @lock)
+ public WriteLock(ReadWriteLock @lock)
{
_isDisposed = 0;
_lock = @lock;
diff --git a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj
index 0c043fd8a11c8a..aae409d311531d 100644
--- a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj
+++ b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj
@@ -41,8 +41,8 @@ System.ComponentModel.Composition.ReflectionModel.ReflectionModelServices
-
+
diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogCollection.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogCollection.cs
index 810834261e25c0..5264003442603a 100644
--- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogCollection.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogCollection.cs
@@ -19,7 +19,7 @@ namespace System.ComponentModel.Composition.Hosting
///
internal sealed class ComposablePartCatalogCollection : ICollection, INotifyComposablePartCatalogChanged, IDisposable
{
- private readonly Lock _lock = new Lock();
+ private readonly ReadWriteLock _lock = new ReadWriteLock();
private readonly Action? _onChanged;
private readonly Action? _onChanging;
private List _catalogs = new List();
diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CompositionLock.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CompositionLock.cs
index 0b6de9492e37b4..53ea59b8fab3ef 100644
--- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CompositionLock.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CompositionLock.cs
@@ -22,7 +22,7 @@ namespace System.ComponentModel.Composition.Hosting
internal sealed class CompositionLock : IDisposable
{
// narrow lock
- private readonly Lock? _stateLock;
+ private readonly ReadWriteLock? _stateLock;
// wide lock
private static readonly object _compositionLock = new object();
@@ -36,7 +36,7 @@ public CompositionLock(bool isThreadSafe)
_isThreadSafe = isThreadSafe;
if (isThreadSafe)
{
- _stateLock = new Lock();
+ _stateLock = new ReadWriteLock();
}
}
diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs
index 0694fb819d5350..201ccada3e5f53 100644
--- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs
@@ -28,7 +28,7 @@ public partial class DirectoryCatalog : ComposablePartCatalog, INotifyComposable
RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
#endif
- private readonly Lock _thisLock = new Lock();
+ private readonly ReadWriteLock _thisLock = new ReadWriteLock();
private readonly ICompositionElement? _definitionOrigin;
private ComposablePartCatalogCollection _catalogCollection;
private Dictionary _assemblyCatalogs;
diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewGenerator.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewGenerator.cs
index 47640c87d93875..c4331dc1ec0c54 100644
--- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewGenerator.cs
+++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewGenerator.cs
@@ -65,7 +65,7 @@ internal static class MetadataViewGenerator
public const string MetadataItemValue = "MetadataItemValue";
public const string MetadataViewFactoryName = "Create";
- private static readonly Lock _lock = new Lock();
+ private static readonly ReadWriteLock _lock = new ReadWriteLock();
private static readonly Dictionary _metadataViewFactories = new Dictionary();
private static readonly AssemblyName ProxyAssemblyName = new AssemblyName($"MetadataViewProxies_{Guid.NewGuid()}");
private static ModuleBuilder? transparentProxyModuleBuilder;
diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TimerTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TimerTests.cs
index ff4138d6cc6f0a..0904d7145912ea 100644
--- a/src/libraries/System.ComponentModel.TypeConverter/tests/TimerTests.cs
+++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TimerTests.cs
@@ -36,7 +36,6 @@ public void Ctor_PropertiesMatchExpectedDefaults()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void TestTimerStartAutoReset()
{
using (var timer = new TestTimer(1))
diff --git a/src/libraries/System.Composition/tests/ConcurrencyTests.cs b/src/libraries/System.Composition/tests/ConcurrencyTests.cs
index e015c15cb23308..6801f55a57d32e 100644
--- a/src/libraries/System.Composition/tests/ConcurrencyTests.cs
+++ b/src/libraries/System.Composition/tests/ConcurrencyTests.cs
@@ -28,7 +28,6 @@ public void OnImportsSatisfied()
// This does not test the desired behaviour deterministically,
// but is close enough to be repeatable at least on my machine :)
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void SharedInstancesAreNotVisibleUntilActivationCompletes()
{
var c = CreateContainer(typeof(PausesDuringActivation));
diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAsync.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAsync.cs
index 3f7131ad8db332..1e9eb7b7555bc8 100644
--- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAsync.cs
+++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAsync.cs
@@ -30,7 +30,6 @@ public void TestCurrentCulturesAsync()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public void TestCurrentCulturesWithAwait()
{
var newCurrentCulture = new CultureInfo(CultureInfo.CurrentCulture.Name.Equals("ja-JP", StringComparison.OrdinalIgnoreCase) ? "en-US" : "ja-JP");
diff --git a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
index 2913efbe3cdf6c..85070e1534a8ee 100644
--- a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
+++ b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
@@ -294,7 +294,6 @@ public async Task WritesUsingGetMemoryWorks()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91547", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task CompleteWithLargeWriteThrows()
{
var completeDelay = TimeSpan.FromMilliseconds(10);
diff --git a/src/libraries/System.IO.Pipelines/tests/SchedulerFacts.cs b/src/libraries/System.IO.Pipelines/tests/SchedulerFacts.cs
index 42b92efbc1369c..ba558339b0a057 100644
--- a/src/libraries/System.IO.Pipelines/tests/SchedulerFacts.cs
+++ b/src/libraries/System.IO.Pipelines/tests/SchedulerFacts.cs
@@ -181,7 +181,6 @@ public async Task DefaultReaderSchedulerIgnoresSyncContextIfConfigureAwaitFalse(
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task DefaultReaderSchedulerRunsOnThreadPool()
{
var pipe = new Pipe(new PipeOptions(useSynchronizationContext: false));
@@ -211,7 +210,6 @@ public async Task DefaultReaderSchedulerRunsOnThreadPool()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task DefaultWriterSchedulerRunsOnThreadPool()
{
using (var pool = new TestMemoryPool())
@@ -413,7 +411,6 @@ public async Task DefaultWriterSchedulerIgnoresSynchronizationContext()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task FlushCallbackRunsOnWriterScheduler()
{
using (var pool = new TestMemoryPool())
@@ -459,7 +456,6 @@ public async Task FlushCallbackRunsOnWriterScheduler()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task ReadAsyncCallbackRunsOnReaderScheduler()
{
using (var pool = new TestMemoryPool())
@@ -493,7 +489,6 @@ public async Task ReadAsyncCallbackRunsOnReaderScheduler()
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public async Task ThreadPoolScheduler_SchedulesOnThreadPool()
{
var pipe = new Pipe(new PipeOptions(readerScheduler: PipeScheduler.ThreadPool, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false));
diff --git a/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml b/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml
index 2004f22a5b280c..6cd6653b9e03fd 100644
--- a/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml
+++ b/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml
@@ -97,6 +97,48 @@
ref/net9.0/System.Linq.Expressions.dll
lib/net9.0/System.Linq.Expressions.dll
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.DynamicExpression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
CP0016
M:System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression,System.String,System.Type[],System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
@@ -109,6 +151,96 @@
ref/net9.0/System.Linq.Expressions.dll
lib/net9.0/System.Linq.Expressions.dll
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Dynamic(System.Runtime.CompilerServices.CallSiteBinder,System.Type,System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.GetActionType(System.Type[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.GetDelegateType(System.Type[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.GetFuncType(System.Type[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.Boolean,System.Collections.Generic.IEnumerable{System.Linq.Expressions.ParameterExpression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.Boolean,System.Linq.Expressions.ParameterExpression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.Collections.Generic.IEnumerable{System.Linq.Expressions.ParameterExpression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.Linq.Expressions.ParameterExpression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.String,System.Boolean,System.Collections.Generic.IEnumerable{System.Linq.Expressions.ParameterExpression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression,System.String,System.Collections.Generic.IEnumerable{System.Linq.Expressions.ParameterExpression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
CP0016
M:System.Linq.Expressions.Expression.ListInit(System.Linq.Expressions.NewExpression,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
@@ -133,12 +265,144 @@
ref/net9.0/System.Linq.Expressions.dll
lib/net9.0/System.Linq.Expressions.dll
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Linq.Expressions.Expression):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.MakeDynamic(System.Type,System.Runtime.CompilerServices.CallSiteBinder,System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.TryGetActionType(System.Type[],System.Type@):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ M:System.Linq.Expressions.Expression.TryGetFuncType(System.Type[],System.Type@):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
CP0016
M:System.Runtime.CompilerServices.CallSite`1.Create(System.Runtime.CompilerServices.CallSiteBinder):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
ref/net9.0/System.Linq.Expressions.dll
lib/net9.0/System.Linq.Expressions.dll
+
+ CP0016
+ T:System.Dynamic.BinaryOperationBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.ConvertBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.CreateInstanceBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.DeleteIndexBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.DeleteMemberBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.DynamicMetaObjectBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.DynamicObject:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.GetIndexBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.GetMemberBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.InvokeBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.InvokeMemberBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.SetIndexBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.SetMemberBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
+
+ CP0016
+ T:System.Dynamic.UnaryOperationBinder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute]
+ ref/net9.0/System.Linq.Expressions.dll
+ lib/net9.0/System.Linq.Expressions.dll
+
CP0020
M:System.Linq.Expressions.DynamicExpressionVisitor.#ctor
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
index 400221c2b692c4..58e80c379b106c 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
using System.Linq.Expressions;
@@ -9,6 +10,7 @@ namespace System.Dynamic
///
/// Represents the binary dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class BinaryOperationBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
index 3feb8bd630164b..ba8dc8184683ae 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the convert dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class ConvertBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
index 5fe0fbddc9708a..2d4443ef2506f9 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the create dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class CreateInstanceBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
index b12295b8269700..798c106f182b4e 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic delete index operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class DeleteIndexBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
index 60a7ab2d351e8c..d6b075e1cb6e37 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic delete member operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class DeleteMemberBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
index 7e39da3f5313d9..e8493fd4f4e4d2 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
@@ -3,6 +3,7 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
@@ -19,6 +20,7 @@ namespace System.Dynamic
/// as input. On the other hand, the participates in the
/// binding protocol.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class DynamicMetaObjectBinder : CallSiteBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
index 19910ca7cf67c4..21ba4d3e0e7238 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
@@ -23,6 +23,7 @@ namespace System.Dynamic
/// If a method is not overridden then the does not directly support
/// that behavior and the call site will determine how the binding should be performed.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public class DynamicObject : IDynamicMetaObjectProvider
{
///
@@ -205,6 +206,7 @@ public virtual bool TryGetIndex(GetIndexBinder binder, object[] indexes, out obj
#region MetaDynamic
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
private sealed class MetaDynamic : DynamicMetaObject
{
internal MetaDynamic(Expression expression, DynamicObject value)
@@ -855,6 +857,7 @@ private Expression GetLimitedSelf()
// is only used by DynamicObject.GetMember--it is not expected to
// (and cannot) implement binding semantics. It is just so the DO
// can use the Name and IgnoreCase properties.
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
private sealed class GetBinderAdapter : GetMemberBinder
{
internal GetBinderAdapter(InvokeMemberBinder binder)
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
index 93b086eeb4d9b8..a367ee3daea3e8 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic get index operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class GetIndexBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
index 25cc22354b0a3e..e24d1ea956e6b5 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic get member operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class GetMemberBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
index 1c9f895067d94d..cb144aee5fa7ec 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the invoke dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class InvokeBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
index 634d77b0ad36a2..742df000b2df9f 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the invoke member dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class InvokeMemberBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
index 8be0b539df48a2..9d9522432797d7 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic set index operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class SetIndexBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
index 4f0b805053c972..4f8ec042d3829a 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
+using System.Linq.Expressions;
namespace System.Dynamic
{
///
/// Represents the dynamic set member operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class SetMemberBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
index 6d45ec4741ee4e..886bc89a5a522e 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
using System.Linq.Expressions;
@@ -9,6 +10,7 @@ namespace System.Dynamic
///
/// Represents the unary dynamic operation at the call site, providing the binding semantic and the details about the operation.
///
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
public abstract class UnaryOperationBinder : DynamicMetaObjectBinder
{
///
diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs
index 2969348e143dc2..af8f38b38a778d 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace System.Dynamic
@@ -8,6 +10,7 @@ namespace System.Dynamic
internal static partial class UpdateDelegates
{
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute1(CallSite site, T0 arg0)
{
//
@@ -153,6 +156,7 @@ internal static TRet NoMatch1(CallSite site, T0 arg0)
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute2(CallSite site, T0 arg0, T1 arg1)
{
//
@@ -298,6 +302,7 @@ internal static TRet NoMatch2(CallSite site, T0 arg0, T1 arg1)
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute3(CallSite site, T0 arg0, T1 arg1, T2 arg2)
{
//
@@ -443,6 +448,7 @@ internal static TRet NoMatch3(CallSite site, T0 arg0, T1 arg1,
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute4(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
{
//
@@ -588,6 +594,7 @@ internal static TRet NoMatch4(CallSite site, T0 arg0, T1 a
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute5(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
//
@@ -733,6 +740,7 @@ internal static TRet NoMatch5(CallSite site, T0 arg0,
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute6(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
//
@@ -878,6 +886,7 @@ internal static TRet NoMatch6(CallSite site, T0 ar
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute7(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
//
@@ -1023,6 +1032,7 @@ internal static TRet NoMatch7(CallSite site, T
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute8(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
//
@@ -1168,6 +1178,7 @@ internal static TRet NoMatch8(CallSite sit
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute9(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
//
@@ -1313,6 +1324,7 @@ internal static TRet NoMatch9(CallSite
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static TRet UpdateAndExecute10(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
{
//
@@ -1458,6 +1470,7 @@ internal static TRet NoMatch10(Cal
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid1(CallSite site, T0 arg0)
{
//
@@ -1602,6 +1615,7 @@ internal static void NoMatchVoid1(CallSite site, T0 arg0)
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid2(CallSite site, T0 arg0, T1 arg1)
{
//
@@ -1746,6 +1760,7 @@ internal static void NoMatchVoid2(CallSite site, T0 arg0, T1 arg1)
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid3(CallSite site, T0 arg0, T1 arg1, T2 arg2)
{
//
@@ -1890,6 +1905,7 @@ internal static void NoMatchVoid3(CallSite site, T0 arg0, T1 arg1, T
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid4(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
{
//
@@ -2034,6 +2050,7 @@ internal static void NoMatchVoid4(CallSite site, T0 arg0, T1 arg
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid5(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
//
@@ -2178,6 +2195,7 @@ internal static void NoMatchVoid5(CallSite site, T0 arg0, T1
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid6(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
//
@@ -2322,6 +2340,7 @@ internal static void NoMatchVoid6(CallSite site, T0 arg0
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid7(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
//
@@ -2466,6 +2485,7 @@ internal static void NoMatchVoid7(CallSite site, T0
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid8(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
//
@@ -2610,6 +2630,7 @@ internal static void NoMatchVoid8(CallSite site,
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid9(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
//
@@ -2754,6 +2775,7 @@ internal static void NoMatchVoid9(CallSite s
[Obsolete("pregenerated CallSite.Update delegate", error: true)]
+ [RequiresDynamicCode(Expression.CallSiteRequiresDynamicCode)]
internal static void UpdateAndExecuteVoid10(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
{
//
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs
index 77356647009076..1ebd36b069882e 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
namespace System.Linq.Expressions.Compiler
@@ -14,6 +15,7 @@ internal static partial class DelegateHelpers
/// We use the cache to avoid copying the array, and to cache the
/// created delegate type
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type MakeDelegateType(Type[] types)
{
lock (_DelegateCache)
@@ -90,6 +92,7 @@ private static TypeInfo NextTypeInfo(Type initialArg, TypeInfo curTypeInfo)
public delegate object VBCallSiteDelegate6(T callSite, object instance, ref object arg1, ref object arg2, ref object arg3, ref object arg4, ref object arg5, ref object arg6);
public delegate object VBCallSiteDelegate7(T callSite, object instance, ref object arg1, ref object arg2, ref object arg3, ref object arg4, ref object arg5, ref object arg6, ref object arg7);
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static Type TryMakeVBStyledCallSite(Type[] types)
{
// Shape of VB CallSiteDelegates is CallSite * (instance : obj) * [arg-n : byref obj] -> obj
@@ -127,6 +130,7 @@ private static Type TryMakeVBStyledCallSite(Type[] types)
/// Creates a new delegate, or uses a func/action
/// Note: this method does not cache
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type MakeNewDelegate(Type[] types)
{
Debug.Assert(types != null && types.Length > 0);
@@ -180,6 +184,7 @@ internal static Type MakeNewDelegate(Type[] types)
return result;
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type GetFuncType(Type[] types)
{
switch (types.Length)
@@ -224,6 +229,7 @@ internal static Type GetFuncType(Type[] types)
}
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type GetActionType(Type[] types)
{
switch (types.Length)
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs
index aa940367777db7..db80a9c43fd4c0 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs
@@ -3,6 +3,7 @@
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Dynamic.Utils;
using System.Reflection;
@@ -18,6 +19,7 @@ internal static partial class DelegateHelpers
/// We take the read-only collection of Expression explicitly to avoid allocating memory (an array
/// of types) on lookup of delegate types.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type MakeCallSiteDelegate(ReadOnlyCollection types, Type returnType)
{
lock (_DelegateCache)
@@ -52,6 +54,7 @@ internal static Type MakeCallSiteDelegate(ReadOnlyCollection types,
/// We take the array of MetaObject explicitly to avoid allocating memory (an array of types) on
/// lookup of delegate types.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
internal static Type MakeDeferredSiteDelegate(DynamicMetaObject[] args, Type returnType)
{
lock (_DelegateCache)
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/StackSpiller.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/StackSpiller.cs
index 4012dd1ebbd8b4..6b10eae46d43a9 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/StackSpiller.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/StackSpiller.cs
@@ -462,7 +462,8 @@ private Result RewriteMethodCallExpression(Expression expr, Stack stack)
return cr.Finish(expr);
}
- [RequiresDynamicCode(Expression.NewArrayRequiresDynamicCode)]
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode",
+ Justification = "A NewArrayExpression has already been created. The original creator will get a warning that it is not trim compatible.")]
private Result RewriteNewArrayExpression(Expression expr, Stack stack)
{
var node = (NewArrayExpression)expr;
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/TypeInfoExtensions.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/TypeInfoExtensions.cs
index a2c1ddc189158b..ba17f904741ebf 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/TypeInfoExtensions.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/TypeInfoExtensions.cs
@@ -2,17 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace System.Linq.Expressions.Compiler
{
internal static class TypeInfoExtensions
{
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static Type MakeDelegateType(this DelegateHelpers.TypeInfo info, Type retType, params Expression[] args)
{
return info.MakeDelegateType(retType, (IList)args);
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static Type MakeDelegateType(this DelegateHelpers.TypeInfo info, Type retType, IList args)
{
// nope, go ahead and create it and spend the
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
index d2e1204b2c1640..4b5a73f3588710 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
@@ -240,6 +240,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments)
{
return ExpressionExtension.Dynamic(binder, returnType, arguments);
@@ -261,6 +262,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable arguments)
{
return ExpressionExtension.Dynamic(binder, returnType, arguments);
@@ -282,6 +284,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0)
{
return ExpressionExtension.Dynamic(binder, returnType, arg0);
@@ -304,6 +307,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1)
{
return ExpressionExtension.Dynamic(binder, returnType, arg0, arg1);
@@ -327,6 +331,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2)
{
return ExpressionExtension.Dynamic(binder, returnType, arg0, arg1, arg2);
@@ -351,6 +356,7 @@ int IArgumentProvider.ArgumentCount
/// The DelegateType property of the result will be inferred
/// from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
{
return ExpressionExtension.Dynamic(binder, returnType, arg0, arg1, arg2, arg3);
@@ -369,6 +375,7 @@ int IArgumentProvider.ArgumentCount
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable? arguments)
{
return ExpressionExtension.MakeDynamic(delegateType, binder, arguments);
@@ -1026,6 +1033,7 @@ private static MethodInfo GetValidMethodForDynamic(Type delegateType)
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments)
{
return Dynamic(binder, returnType, (IEnumerable)arguments);
@@ -1047,6 +1055,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0)
{
ArgumentNullException.ThrowIfNull(binder);
@@ -1082,6 +1091,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1)
{
ArgumentNullException.ThrowIfNull(binder);
@@ -1122,6 +1132,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2)
{
ArgumentNullException.ThrowIfNull(binder);
@@ -1167,6 +1178,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
{
ArgumentNullException.ThrowIfNull(binder);
@@ -1213,6 +1225,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable arguments)
{
ArgumentNullException.ThrowIfNull(arguments);
@@ -1223,6 +1236,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
return MakeDynamic(binder, returnType, args);
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection arguments)
{
ArgumentNullException.ThrowIfNull(binder);
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Expression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Expression.cs
index 690f234fae7298..0458fc01830e6d 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Expression.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Expression.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic.Utils;
using System.Globalization;
using System.Reflection;
@@ -25,6 +26,7 @@ public abstract partial class Expression
internal const string LambdaCompilerRequiresDynamicCode = "Compiling a lambda expression requires dynamic code generation.";
internal const string StrongBoxRequiresDynamicCode = "Creating a StrongBox requires dynamic code generation.";
internal const string NewArrayRequiresDynamicCode = "Creating arrays at runtime requires dynamic code generation.";
+ internal const string DelegateCreationRequiresDynamicCode = "Delegate creation requires dynamic code generation.";
private static readonly CacheDict s_lambdaDelegateCache = new CacheDict(40);
private static volatile CacheDict, LambdaExpression>>? s_lambdaFactories;
@@ -298,6 +300,7 @@ private static void RequiresCanWrite(Expression expression, string paramName)
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable arguments) =>
DynamicExpression.Dynamic(binder, returnType, arguments);
@@ -317,6 +320,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0) =>
DynamicExpression.Dynamic(binder, returnType, arg0);
@@ -337,6 +341,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1) =>
DynamicExpression.Dynamic(binder, returnType, arg0, arg1);
@@ -358,6 +363,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2) =>
DynamicExpression.Dynamic(binder, returnType, arg0, arg1, arg2);
@@ -380,6 +386,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3) =>
DynamicExpression.Dynamic(binder, returnType, arg0, arg1, arg2, arg3);
@@ -399,6 +406,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments) =>
DynamicExpression.Dynamic(binder, returnType, arguments);
@@ -415,6 +423,7 @@ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType,
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable? arguments) =>
DynamicExpression.MakeDynamic(delegateType, binder, arguments);
@@ -431,6 +440,7 @@ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder bi
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0) =>
DynamicExpression.MakeDynamic(delegateType, binder, arg0);
@@ -448,6 +458,7 @@ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder bi
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) =>
DynamicExpression.MakeDynamic(delegateType, binder, arg0, arg1);
@@ -466,6 +477,7 @@ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder bi
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) =>
DynamicExpression.MakeDynamic(delegateType, binder, arg0, arg1, arg2);
@@ -485,6 +497,7 @@ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder bi
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) =>
DynamicExpression.MakeDynamic(delegateType, binder, arg0, arg1, arg2, arg3);
@@ -501,6 +514,7 @@ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder bi
/// Binder, and
/// Arguments set to the specified values.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[]? arguments) =>
MakeDynamic(delegateType, binder, (IEnumerable?)arguments);
}
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs
index 34203b5512d280..96bc1894bae8ef 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs
@@ -32,6 +32,7 @@ internal partial class CallInstruction
/// One relaxation is that for return types which are non-primitive types
/// we can fall back to object due to relaxed delegates.
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[] pi)
{
Type t = TryGetParameterOrReturnType(target, pi, 0);
@@ -71,6 +72,7 @@ private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[] pi)
}
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[] pi)
{
Type t = TryGetParameterOrReturnType(target, pi, 1);
@@ -114,6 +116,7 @@ private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[]
}
}
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[] pi)
{
Type t = TryGetParameterOrReturnType(target, pi, 2);
@@ -157,6 +160,7 @@ private static CallInstruction FastCreate(MethodInfo target, ParameterIn
#endif
[return: DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static Type GetHelperType(MethodInfo info, Type[] arrTypes)
{
Type t;
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
index 5ab0cea57217b1..f73d513a25d07a 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
@@ -50,6 +50,8 @@ public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters
if (!CanCreateArbitraryDelegates)
return new MethodInfoCallInstruction(info, argumentCount);
+ // This code should be unreachable in AOT. The analyzer currently doesn't understand feature switches
+#pragma warning disable IL3050
if (!info.IsStatic && info.DeclaringType!.IsValueType)
{
return new MethodInfoCallInstruction(info, argumentCount);
@@ -113,6 +115,7 @@ public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters
s_cache[info] = res;
return res;
+#pragma warning restore IL3050
}
private static CallInstruction GetArrayAccessor(MethodInfo info, int argumentCount)
@@ -205,6 +208,7 @@ private static bool IndexIsNotReturnType(int index, MethodInfo target, Parameter
///
/// Uses reflection to create new instance of the appropriate ReflectedCaller
///
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
private static CallInstruction SlowCreate(MethodInfo info, ParameterInfo[] pis)
{
List types = new List();
diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
index 9b22fc9bc6e95b..d3f0366a01f386 100644
--- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
+++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
@@ -742,6 +742,7 @@ public static Expression Lambda(Expression body, string? n
/// An to set the property equal to.
/// An array that contains objects to use to populate the collection.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, params ParameterExpression[]? parameters)
{
return Lambda(body, false, (IEnumerable?)parameters);
@@ -754,6 +755,7 @@ public static LambdaExpression Lambda(Expression body, params ParameterExpressio
/// A that indicates if tail call optimization will be applied when compiling the created expression.
/// An array that contains objects to use to populate the collection.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, bool tailCall, params ParameterExpression[]? parameters)
{
return Lambda(body, tailCall, (IEnumerable?)parameters);
@@ -765,6 +767,7 @@ public static LambdaExpression Lambda(Expression body, bool tailCall, params Par
/// An to set the property equal to.
/// An that contains objects to use to populate the collection.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, IEnumerable? parameters)
{
return Lambda(body, null, false, parameters);
@@ -777,6 +780,7 @@ public static LambdaExpression Lambda(Expression body, IEnumerableA that indicates if tail call optimization will be applied when compiling the created expression.
/// An that contains objects to use to populate the collection.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, bool tailCall, IEnumerable? parameters)
{
return Lambda(body, null, tailCall, parameters);
@@ -839,6 +843,7 @@ public static LambdaExpression Lambda(Type delegateType, Expression body, bool t
/// An that contains objects to use to populate the collection.
/// The name for the lambda. Used for emitting debug information.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, string? name, IEnumerable? parameters)
{
return Lambda(body, name, false, parameters);
@@ -852,6 +857,7 @@ public static LambdaExpression Lambda(Expression body, string? name, IEnumerable
/// A that indicates if tail call optimization will be applied when compiling the created expression.
/// An that contains objects to use to populate the collection.
/// A that has the property equal to and the and properties set to the specified values.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static LambdaExpression Lambda(Expression body, string? name, bool tailCall, IEnumerable? parameters)
{
ArgumentNullException.ThrowIfNull(body);
@@ -1026,6 +1032,7 @@ private static TryGetFuncActionArgsResult ValidateTryGetFuncActionArgs(Type[]? t
///
/// An array of objects that specify the type arguments for the System.Func delegate type.
/// The type of a System.Func delegate that has the specified type arguments.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static Type GetFuncType(params Type[]? typeArgs)
{
switch (ValidateTryGetFuncActionArgs(typeArgs))
@@ -1055,6 +1062,7 @@ public static Type GetFuncType(params Type[]? typeArgs)
/// An array of objects that specify the type arguments for the System.Func delegate type.
/// When this method returns, contains the generic System.Func delegate type that has specific type arguments. Contains null if there is no generic System.Func delegate that matches the .This parameter is passed uninitialized.
/// true if generic System.Func delegate type was created for specific ; false otherwise.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static bool TryGetFuncType(Type[] typeArgs, [NotNullWhen(true)] out Type? funcType)
{
if (ValidateTryGetFuncActionArgs(typeArgs) == TryGetFuncActionArgsResult.Valid)
@@ -1071,6 +1079,7 @@ public static bool TryGetFuncType(Type[] typeArgs, [NotNullWhen(true)] out Type?
///
/// An array of objects that specify the type arguments for the System.Action delegate type.
/// The type of a System.Action delegate that has the specified type arguments.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static Type GetActionType(params Type[]? typeArgs)
{
switch (ValidateTryGetFuncActionArgs(typeArgs))
@@ -1099,6 +1108,7 @@ public static Type GetActionType(params Type[]? typeArgs)
/// An array of objects that specify the type arguments for the System.Action delegate type.
/// When this method returns, contains the generic System.Action delegate type that has specific type arguments. Contains null if there is no generic System.Action delegate that matches the .This parameter is passed uninitialized.
/// true if generic System.Action delegate type was created for specific ; false otherwise.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static bool TryGetActionType(Type[] typeArgs, [NotNullWhen(true)] out Type? actionType)
{
if (ValidateTryGetFuncActionArgs(typeArgs) == TryGetFuncActionArgsResult.Valid)
@@ -1120,6 +1130,7 @@ public static bool TryGetActionType(Type[] typeArgs, [NotNullWhen(true)] out Typ
///
/// As with Func, the last argument is the return type. It can be set
/// to to produce an Action.
+ [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)]
public static Type GetDelegateType(params Type[] typeArgs)
{
ContractUtils.RequiresNotEmpty(typeArgs, nameof(typeArgs));
diff --git a/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs b/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs
index 3f12e3e34c0027..6dcaffbf60a5a5 100644
--- a/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs
+++ b/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs
@@ -89,7 +89,6 @@ public static IEnumerable AllMergeOptions_Multiple()
// or WithMergeOptions
[ConditionalTheory]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(PartitioningData), new[] { 0, 1, 2, 16, 1024 })]
public static void Partitioning_Default(Labeled> labeled, int count, int partitions)
{
@@ -159,7 +158,6 @@ public static void Merge_Ordered_Longrunning(Labeled> labeled
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(ThrowOnCount_AllMergeOptions_MemberData), new[] { 4, 8 })]
// FailingMergeData has enumerables that throw errors when attempting to perform the nth enumeration.
// This test checks whether the query runs in a pipelined or buffered fashion.
@@ -169,7 +167,6 @@ public static void Merge_Ordered_Pipelining(Labeled> labeled,
}
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(MergeData), new[] { 4, 8 })]
// This test checks whether the query runs in a pipelined or buffered fashion.
public static void Merge_Ordered_Pipelining_Select(Labeled> labeled, int count, ParallelMergeOptions options)
diff --git a/src/libraries/System.Linq.Parallel/tests/PlinqModesTests.cs b/src/libraries/System.Linq.Parallel/tests/PlinqModesTests.cs
index 85db2d3805bf48..b6b8b626c51588 100644
--- a/src/libraries/System.Linq.Parallel/tests/PlinqModesTests.cs
+++ b/src/libraries/System.Linq.Parallel/tests/PlinqModesTests.cs
@@ -136,7 +136,6 @@ public static IEnumerable AllExecutionModes_Multiple()
// Check that some queries run in parallel by default, and some require forcing.
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91661", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
[MemberData(nameof(WithExecutionModeQueryData), new[] { 1, 4 })] // DOP of 1 to verify sequential and 4 to verify parallel
public static void WithExecutionMode(
Labeled> labeled,
diff --git a/src/libraries/System.Linq.Parallel/tests/QueryOperators/GetEnumeratorTests.cs b/src/libraries/System.Linq.Parallel/tests/QueryOperators/GetEnumeratorTests.cs
index 652c72897980da..d34cc6e903bc9c 100644
--- a/src/libraries/System.Linq.Parallel/tests/QueryOperators/GetEnumeratorTests.cs
+++ b/src/libraries/System.Linq.Parallel/tests/QueryOperators/GetEnumeratorTests.cs
@@ -165,7 +165,6 @@ public static void GetEnumerator_MoveNextAfterEnd(Labeled> la
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public static void GetEnumerator_LargeQuery_PauseAfterOpening()
{
using (IEnumerator e = Enumerable.Range(0, 8192).AsParallel().SkipWhile(i => true).GetEnumerator())
diff --git a/src/libraries/System.Linq.Parallel/tests/QueryOperators/OrderByThenByTests.cs b/src/libraries/System.Linq.Parallel/tests/QueryOperators/OrderByThenByTests.cs
index 931333fd69b536..0d920b5d13f782 100644
--- a/src/libraries/System.Linq.Parallel/tests/QueryOperators/OrderByThenByTests.cs
+++ b/src/libraries/System.Linq.Parallel/tests/QueryOperators/OrderByThenByTests.cs
@@ -517,7 +517,6 @@ public static void OrderBy_ThreadedDeadlock(Labeled> labeled,
// Heavily exercises OrderBy, but only throws one user delegate exception to simulate an occasional failure.
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[MemberData(nameof(OrderByThreadedData), new[] { 1, 2, 16, 128, 1024 }, new[] { 1, 2, 4, 7, 8, 31, 32 })]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))]
public static void OrderBy_ThreadedDeadlock_SingleException(Labeled> labeled, int count, int degree)
{
int countdown = Math.Min(count / 2, degree) + 1;
diff --git a/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs
index a058b6048c2c4d..caf83bee1fcaac 100644
--- a/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs
+++ b/src/libraries/System.Linq/src/System/Linq/AppendPrepend.SpeedOpt.cs
@@ -73,6 +73,13 @@ public override TSource[] ToArray()
public override List ToList()
{
int count = GetCount(onlyIfCheap: true);
+
+ if (count == 1)
+ {
+ // If GetCount returns 1, then _source is empty and only _item should be returned
+ return new List(1) { _item };
+ }
+
List list = count == -1 ? new List() : new List(count);
if (!_appending)
{
@@ -122,17 +129,8 @@ private TSource[] LazyToArray()
TSource[] array = builder.ToArray();
- int index = 0;
- for (SingleLinkedNode? node = _prepended; node != null; node = node.Linked)
- {
- array[index++] = node.Item;
- }
-
- index = array.Length - 1;
- for (SingleLinkedNode? node = _appended; node != null; node = node.Linked)
- {
- array[index--] = node.Item;
- }
+ _prepended?.Fill(array);
+ _appended?.FillReversed(array);
return array;
}
@@ -181,17 +179,11 @@ public override List ToList()
int count = GetCount(onlyIfCheap: true);
List list = count == -1 ? new List() : new List(count);
- for (SingleLinkedNode? node = _prepended; node != null; node = node.Linked)
- {
- list.Add(node.Item);
- }
+ _prepended?.Fill(SetCountAndGetSpan(list, _prependCount));
list.AddRange(_source);
- if (_appended != null)
- {
- list.AddRange(_appended.ToArray(_appendCount));
- }
+ _appended?.FillReversed(SetCountAndGetSpan(list, list.Count + _appendCount));
return list;
}
diff --git a/src/libraries/System.Linq/src/System/Linq/Lookup.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/Lookup.SpeedOpt.cs
index 5fc89fc52555b6..2ef86a008493a8 100644
--- a/src/libraries/System.Linq/src/System/Linq/Lookup.SpeedOpt.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Lookup.SpeedOpt.cs
@@ -10,22 +10,16 @@ public partial class Lookup : IIListProvider[] IIListProvider>.ToArray()
{
- IGrouping[] array = new IGrouping[_count];
- int index = 0;
- Grouping? g = _lastGrouping;
- if (g != null)
+ IGrouping[] array;
+ if (_count > 0)
{
- do
- {
- g = g._next;
- Debug.Assert(g != null);
-
- array[index] = g;
- ++index;
- }
- while (g != _lastGrouping);
+ array = new IGrouping[_count];
+ Fill(_lastGrouping, array);
+ }
+ else
+ {
+ array = Array.Empty>();
}
-
return array;
}
@@ -53,8 +47,19 @@ internal TResult[] ToArray(Func, TResult> r
List> IIListProvider>.ToList()
{
- List> list = new List>(_count);
- Grouping? g = _lastGrouping;
+ var list = new List>(_count);
+ if (_count > 0)
+ {
+ Fill(_lastGrouping, Enumerable.SetCountAndGetSpan(list, _count));
+ }
+
+ return list;
+ }
+
+ private static void Fill(Grouping? lastGrouping, Span> results)
+ {
+ int index = 0;
+ Grouping? g = lastGrouping;
if (g != null)
{
do
@@ -62,12 +67,13 @@ List> IIListProvider>.ToList
g = g._next;
Debug.Assert(g != null);
- list.Add(g);
+ results[index] = g;
+ ++index;
}
- while (g != _lastGrouping);
+ while (g != lastGrouping);
}
- return list;
+ Debug.Assert(index == results.Length, "All list elements were not initialized.");
}
int IIListProvider>.GetCount(bool onlyIfCheap) => _count;
diff --git a/src/libraries/System.Linq/src/System/Linq/Lookup.cs b/src/libraries/System.Linq/src/System/Linq/Lookup.cs
index 2ee2d329255eb9..4e40e9c2e695d2 100644
--- a/src/libraries/System.Linq/src/System/Linq/Lookup.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Lookup.cs
@@ -154,15 +154,20 @@ internal List ToList(Func, TResult
Grouping? g = _lastGrouping;
if (g != null)
{
+ Span span = Enumerable.SetCountAndGetSpan(list, _count);
+ int index = 0;
do
{
g = g._next;
Debug.Assert(g != null);
g.Trim();
- list.Add(resultSelector(g._key, g._elements));
+ span[index] = resultSelector(g._key, g._elements);
+ ++index;
}
while (g != _lastGrouping);
+
+ Debug.Assert(index == _count, "All list elements were not initialized.");
}
return list;
diff --git a/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs
index 7eed5849965e97..faf09335d5f3a3 100644
--- a/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs
@@ -611,13 +611,7 @@ private TResult[] PreallocatingToArray(int count)
Debug.Assert(count == _source.GetCount(onlyIfCheap: true));
TResult[] array = new TResult[count];
- int index = 0;
- foreach (TSource input in _source)
- {
- array[index] = _selector(input);
- ++index;
- }
-
+ Fill(_source, array, _selector);
return array;
}
@@ -640,20 +634,33 @@ public List ToList()
{
case -1:
list = new List();
+ foreach (TSource input in _source)
+ {
+ list.Add(_selector(input));
+ }
break;
case 0:
- return new List();
+ list = new List();
+ break;
default:
list = new List(count);
+ Fill(_source, SetCountAndGetSpan(list, count), _selector);
break;
}
- foreach (TSource input in _source)
+ return list;
+ }
+
+ private static void Fill(IPartition source, Span results, Func func)
+ {
+ int index = 0;
+ foreach (TSource item in source)
{
- list.Add(_selector(input));
+ results[index] = func(item);
+ ++index;
}
- return list;
+ Debug.Assert(index == results.Length, "All list elements were not initialized.");
}
public int GetCount(bool onlyIfCheap)
diff --git a/src/libraries/System.Linq/src/System/Linq/SingleLinkedNode.cs b/src/libraries/System.Linq/src/System/Linq/SingleLinkedNode.cs
index 37a4a3a60c5582..7468973d2c77c0 100644
--- a/src/libraries/System.Linq/src/System/Linq/SingleLinkedNode.cs
+++ b/src/libraries/System.Linq/src/System/Linq/SingleLinkedNode.cs
@@ -92,15 +92,36 @@ public TSource[] ToArray(int count)
Debug.Assert(count == GetCount());
TSource[] array = new TSource[count];
- int index = count;
+ FillReversed(array);
+ return array;
+ }
+
+ ///
+ /// Fills a start of a span with the items of this node's singly-linked list.
+ ///
+ /// The span to fill. Must be the precise size required.
+ public void Fill(Span span)
+ {
+ int index = 0;
for (SingleLinkedNode? node = this; node != null; node = node.Linked)
{
- --index;
- array[index] = node.Item;
+ span[index] = node.Item;
+ index++;
}
+ }
- Debug.Assert(index == 0);
- return array;
+ ///
+ /// Fills the end of a span with the items of this node's singly-linked list in reverse.
+ ///
+ /// The span to fill.
+ public void FillReversed(Span span)
+ {
+ int index = span.Length;
+ for (SingleLinkedNode? node = this; node != null; node = node.Linked)
+ {
+ --index;
+ span[index] = node.Item;
+ }
}
}
}
diff --git a/src/libraries/System.Linq/src/System/Linq/ToCollection.cs b/src/libraries/System.Linq/src/System/Linq/ToCollection.cs
index 280ced4d34f629..aaf9b86dc93a54 100644
--- a/src/libraries/System.Linq/src/System/Linq/ToCollection.cs
+++ b/src/libraries/System.Linq/src/System/Linq/ToCollection.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics;
namespace System.Linq
{
@@ -255,11 +256,21 @@ private static TSource[] HashSetToArray(HashSet set)
private static List HashSetToList(HashSet set)
{
- var result = new List(set.Count);
+ int count = set.Count;
- foreach (TSource item in set)
+ var result = new List(count);
+ if (count > 0)
{
- result.Add(item);
+ Span span = SetCountAndGetSpan(result, count);
+
+ int index = 0;
+ foreach (TSource item in set)
+ {
+ span[index] = item;
+ ++index;
+ }
+
+ Debug.Assert(index == span.Length, "All list elements were not initialized.");
}
return result;
diff --git a/src/libraries/System.Linq/tests/SelectTests.cs b/src/libraries/System.Linq/tests/SelectTests.cs
index 20de7814b6bcca..1f709bf9caadaf 100644
--- a/src/libraries/System.Linq/tests/SelectTests.cs
+++ b/src/libraries/System.Linq/tests/SelectTests.cs
@@ -1107,6 +1107,13 @@ public void Select_SourceIsArrayTakeTake()
Assert.Equal(new[] { 2 }, source.Take(10));
}
+ [Fact]
+ public void Select_SourceIsIPartitionToArray()
+ {
+ Assert.Equal(Array.Empty(), new List().Order().Select(i => i * 2).ToArray());
+ Assert.Equal(new[] { 2, 4, 6, 8 }, new List { 1, 2, 3, 4 }.Order().Select(i => i * 2).ToArray());
+ }
+
[Fact]
public void Select_SourceIsListSkipTakeCount()
{
@@ -1134,6 +1141,13 @@ public void Select_SourceIsListSkipTakeToList()
Assert.Empty(new List { 1, 2, 3, 4 }.Select(i => i * 2).Skip(8).ToList());
}
+ [Fact]
+ public void Select_SourceIsIPartitionToList()
+ {
+ Assert.Equal(Array.Empty(), new List().Order().Select(i => i * 2).ToList());
+ Assert.Equal(new[] { 2, 4, 6, 8 }, new List { 1, 2, 3, 4 }.Order().Select(i => i * 2).ToList());
+ }
+
[Theory]
[MemberData(nameof(MoveNextAfterDisposeData))]
public void MoveNextAfterDispose(IEnumerable source)
diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestCallback.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestCallback.cs
index 13c154516ce82c..7542c42fab9b49 100644
--- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestCallback.cs
+++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestCallback.cs
@@ -231,13 +231,12 @@ private static void OnRequestRedirect(WinHttpRequestState state, Uri redirectUri
private static void OnRequestSendingRequest(WinHttpRequestState state)
{
Debug.Assert(state != null, "OnRequestSendingRequest: state is null");
- Debug.Assert(state.RequestHandle != null, "OnRequestSendingRequest: state.RequestHandle is null");
Debug.Assert(state.RequestMessage != null, "OnRequestSendingRequest: state.RequestMessage is null");
Debug.Assert(state.RequestMessage.RequestUri != null, "OnRequestSendingRequest: state.RequestMessage.RequestUri is null");
- if (state.RequestMessage.RequestUri.Scheme != UriScheme.Https)
+ if (state.RequestMessage.RequestUri.Scheme != UriScheme.Https || state.RequestHandle == null)
{
- // Not SSL/TLS.
+ // Not SSL/TLS or request already gone
return;
}
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj
index fdb94e9caff24d..d0283202019b22 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj
@@ -25,7 +25,6 @@
$(TestArchiveTestsRoot)$(OSPlatformConfig)/
$(DefineConstants);TARGET_BROWSER
--setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot
- <_WasmPThreadPoolSize Condition="'$(MonoWasmBuildVariant)' == 'multithread'">10
01:15:00
diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs
index 7fbb92a2717428..f5b702d8ec77a6 100644
--- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs
+++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs
@@ -137,6 +137,12 @@ public async Task Connect_AfterDisconnect_Fails()
[InlineData("[::ffff:1.1.1.1]", true, false)]
public async Task ConnectGetsCanceledByDispose(string addressString, bool useDns, bool owning)
{
+ if (UsesSync && !PlatformDetection.IsWindows)
+ {
+ // [ActiveIssue("https://github.com/dotnet/runtime/issues/94149", TestPlatforms.Linux)]
+ return;
+ }
+
// Aborting sync operations for non-owning handles is not supported on Unix.
if (!owning && UsesSync && !PlatformDetection.IsWindows)
{
diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/TelemetryTest.cs
index 851b68288fd866..6886fa15e45d0b 100644
--- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/TelemetryTest.cs
+++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/TelemetryTest.cs
@@ -187,6 +187,7 @@ await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), asyn
}, connectMethod, useDnsEndPoint.ToString()).Dispose();
}
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/94149", TestPlatforms.Linux)]
[OuterLoop]
[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD, "Same as Connect.ConnectGetsCanceledByDispose")]
diff --git a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj
index f683a4bcf3d949..fe0d13c9526231 100644
--- a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj
+++ b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj
@@ -14,7 +14,6 @@
$(TestArchiveTestsRoot)$(OSPlatformConfig)/
$(DefineConstants);TARGET_BROWSER
--setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot
- <_WasmPThreadPoolSize Condition="'$(MonoWasmBuildVariant)' == 'multithread'">10
01:15:00
diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
index b8f8a8980528c7..007ffdbdc6fed4 100644
--- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
@@ -1,17 +1,17 @@
-
@@ -376,7 +376,7 @@
One of the identified items was in an invalid format.
-
+
Generic arguments after array spec or pointer type.
@@ -1080,7 +1080,7 @@
Field '{0}' does not belong to the same class as the constructor.
-
+
Field '{0}' does not have a valid type.
@@ -1502,7 +1502,7 @@
Path cannot be the empty string or all whitespace.
- Value of argument {0} does not match parameter type: {1} -> {2}.
+ Value of argument {0} does not match parameter type: {1} -> {2}.
Parameter {0} does not have a valid type.
@@ -3434,7 +3434,13 @@
Setter must have parameters.
-
+
+ The lock has reached the limit of recursive enters.
+
+
+ The lock has reached the limit of how many threads may wait for the lock.
+
+
The calling thread does not hold the lock.
@@ -3774,7 +3780,7 @@
"Property '{0}' does not have a setter.
- "Value of property '{0}' does not match property type: '{1}' -> '{2}'.
+ "Value of property '{0}' does not match property type: '{1}' -> '{2}'.
Cannot load hostpolicy library. AssemblyDependencyResolver is currently only supported if the runtime is hosted through hostpolicy library.
@@ -4253,4 +4259,25 @@
SearchValues<string> supports only StringComparison.Ordinal and StringComparison.OrdinalIgnoreCase.
-
+
+ ComVariants containing SAFEARRAYs are not supported on this platform
+
+
+ Size of {0} should be the same size as the value specified by {1}
+
+
+ Variant type '{0}' is not one of the supported variant types for this operation: [{1}]
+
+
+ VT_DECIMAL is not supported in CreateRaw. Use the Create method.
+
+
+ VT_DECIMAL is not supported in GetRawDataRef. Use the As method.
+
+
+ VT_VARIANT is not supported in variants.
+
+
+ Unsupported type
+
+
\ No newline at end of file
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index ed3325afbec528..499142574857f4 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -418,7 +418,6 @@
-
@@ -674,7 +673,9 @@
+
+
@@ -977,6 +978,7 @@
+
@@ -1200,6 +1202,8 @@
+
+
@@ -1788,8 +1792,8 @@
Common\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs
-
- Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs
+
+ Common\Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs
Common\Interop\Windows\Kernel32\Interop.GetFileAttributesEx.cs
@@ -2052,6 +2056,9 @@
Common\Interop\Windows\Ole32\Interop.CoTaskMemAlloc.cs
+
+ Common\Interop\Windows\Ole32\Interop.PropVariantClear.cs
+
Common\Interop\Windows\Secur32\Interop.GetUserNameExW.cs
@@ -2402,6 +2409,9 @@
Common\Interop\Unix\System.Native\Interop.SysLog.cs
+
+ Common\Interop\Unix\System.Native\Interop.Threading.cs
+
Common\Interop\Unix\System.Native\Interop.Unlink.cs
diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs b/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs
index efbe9e691625d7..c16f72184736b1 100644
--- a/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs
@@ -7,18 +7,25 @@ namespace System
{
internal static class AppContextConfigHelper
{
- internal static bool GetBooleanConfig(string configName, bool defaultValue) =>
- AppContext.TryGetSwitch(configName, out bool value) ? value : defaultValue;
+ internal static bool GetBooleanConfig(string switchName, bool defaultValue) =>
+ AppContext.TryGetSwitch(switchName, out bool value) ? value : defaultValue;
internal static bool GetBooleanConfig(string switchName, string envVariable, bool defaultValue = false)
{
- if (!AppContext.TryGetSwitch(switchName, out bool ret))
+ string? str = Environment.GetEnvironmentVariable(envVariable);
+ if (str != null)
{
- string? switchValue = Environment.GetEnvironmentVariable(envVariable);
- ret = switchValue != null ? (bool.IsTrueStringIgnoreCase(switchValue) || switchValue.Equals("1")) : defaultValue;
+ if (str.Equals("1", StringComparison.Ordinal) || bool.IsTrueStringIgnoreCase(str))
+ {
+ return true;
+ }
+ if (str.Equals("0", StringComparison.Ordinal) || bool.IsFalseStringIgnoreCase(str))
+ {
+ return false;
+ }
}
- return ret;
+ return GetBooleanConfig(switchName, defaultValue);
}
internal static int GetInt32Config(string configName, int defaultValue, bool allowNegative = true)
diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs
index e4ec370796bf60..5561c8ec3a4200 100644
--- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs
@@ -19,6 +19,8 @@ namespace System
// (ie, users could assign a new value to the old location).
[Serializable]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [DebuggerTypeProxy(typeof(ICollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
#pragma warning disable CA1066 // adding IEquatable implementation could change semantics of code like that in xunit that queries for IEquatable vs enumerating contents
public readonly struct ArraySegment : IList, IReadOnlyList
#pragma warning restore CA1066
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.NativeSinks.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.NativeSinks.cs
index ad7ee54ae227a4..1cf9b4fecd6dbc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.NativeSinks.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.NativeSinks.cs
@@ -83,6 +83,12 @@ private void ContentionLockCreated(nint LockID, nint AssociatedObjectID, ushort
LogContentionLockCreated(LockID, AssociatedObjectID, ClrInstanceID);
}
+#pragma warning disable CA2252 // Opt in to preview features before using them (Lock)
+ [NonEvent]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void ContentionLockCreated(Lock lockObj) => ContentionLockCreated(lockObj.LockIdForEvents, lockObj.ObjectIdForEvents);
+#pragma warning restore CA2252
+
[Event(81, Level = EventLevel.Informational, Message = Messages.ContentionStart, Task = Tasks.Contention, Opcode = EventOpcode.Start, Version = 2, Keywords = Keywords.ContentionKeyword)]
private void ContentionStart(
ContentionFlagsMap ContentionFlags,
@@ -95,6 +101,18 @@ private void ContentionStart(
LogContentionStart(ContentionFlags, ClrInstanceID, LockID, AssociatedObjectID, LockOwnerThreadID);
}
+#pragma warning disable CA2252 // Opt in to preview features before using them (Lock)
+ [NonEvent]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void ContentionStart(Lock lockObj) =>
+ ContentionStart(
+ ContentionFlagsMap.Managed,
+ DefaultClrInstanceId,
+ lockObj.LockIdForEvents,
+ lockObj.ObjectIdForEvents,
+ lockObj.OwningThreadId);
+#pragma warning restore CA2252
+
[Event(91, Level = EventLevel.Informational, Message = Messages.ContentionStop, Task = Tasks.Contention, Opcode = EventOpcode.Stop, Version = 1, Keywords = Keywords.ContentionKeyword)]
private void ContentionStop(ContentionFlagsMap ContentionFlags, ushort ClrInstanceID, double DurationNs)
{
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.cs
index c7a6d96aab2ba2..668547832733ea 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.Threading.cs
@@ -95,6 +95,12 @@ private unsafe void ContentionLockCreated(nint LockID, nint AssociatedObjectID,
WriteEventCore(90, 3, data);
}
+#pragma warning disable CA2252 // Opt in to preview features before using them (Lock)
+ [NonEvent]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void ContentionLockCreated(Lock lockObj) => ContentionLockCreated(lockObj.LockIdForEvents, lockObj.ObjectIdForEvents);
+#pragma warning restore CA2252
+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = "Parameters to this method are primitive and are trimmer safe")]
[Event(81, Level = EventLevel.Informational, Message = Messages.ContentionStart, Task = Tasks.Contention, Opcode = EventOpcode.Start, Version = 2, Keywords = Keywords.ContentionKeyword)]
private unsafe void ContentionStart(
@@ -125,6 +131,18 @@ private unsafe void ContentionStart(
WriteEventCore(81, 3, data);
}
+#pragma warning disable CA2252 // Opt in to preview features before using them (Lock)
+ [NonEvent]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void ContentionStart(Lock lockObj) =>
+ ContentionStart(
+ ContentionFlagsMap.Managed,
+ DefaultClrInstanceId,
+ lockObj.LockIdForEvents,
+ lockObj.ObjectIdForEvents,
+ lockObj.OwningThreadId);
+#pragma warning restore CA2252
+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = "Parameters to this method are primitive and are trimmer safe")]
[Event(91, Level = EventLevel.Informational, Message = Messages.ContentionStop, Task = Tasks.Contention, Opcode = EventOpcode.Stop, Version = 1, Keywords = Keywords.ContentionKeyword)]
private unsafe void ContentionStop(ContentionFlagsMap ContentionFlags, ushort ClrInstanceID, double DurationNs)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
new file mode 100644
index 00000000000000..7c38c287bf22b5
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Reflection.Emit
+{
+ public abstract class LocalBuilder : LocalVariableInfo
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// This constructor is invoked by derived classes.
+ ///
+ protected LocalBuilder() { }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ComVariant.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ComVariant.cs
new file mode 100644
index 00000000000000..95a102338e6211
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ComVariant.cs
@@ -0,0 +1,569 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ ///
+ /// A type that represents an OLE VARIANT in managed code.
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct ComVariant : IDisposable
+ {
+ // See definition in wtypes.h in the Windows SDK.
+ private const VarEnum VT_VERSIONED_STREAM = (VarEnum)73;
+ // VARIANT_BOOL constants.
+ internal const short VARIANT_TRUE = -1;
+ internal const short VARIANT_FALSE = 0;
+#if DEBUG
+ static unsafe ComVariant()
+ {
+ // Variant size is the size of 4 pointers (16 bytes) on a 32-bit processor,
+ // and 3 pointers (24 bytes) on a 64-bit processor.
+ // See definition in oaidl.h in the Windows SDK.
+ int variantSize = sizeof(ComVariant);
+ if (IntPtr.Size == 4)
+ {
+ Debug.Assert(variantSize == (4 * IntPtr.Size));
+ }
+ else
+ {
+ Debug.Assert(IntPtr.Size == 8);
+ Debug.Assert(variantSize == (3 * IntPtr.Size));
+ }
+ }
+#endif
+
+ // Most of the data types in the Variant are carried in _typeUnion
+ [FieldOffset(0)] private TypeUnion _typeUnion;
+
+ // Decimal is the largest data type and it needs to use the space that is normally unused in TypeUnion._wReserved1, etc.
+ // Hence, it is declared to completely overlap with TypeUnion. A Decimal does not use the first two bytes, and so
+ // TypeUnion._vt can still be used to encode the type.
+ [FieldOffset(0)] private decimal _decimal;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct TypeUnion
+ {
+ public ushort _vt;
+ public ushort _wReserved1;
+ public ushort _wReserved2;
+ public ushort _wReserved3;
+
+ public UnionTypes _unionTypes;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct Record
+ {
+ public IntPtr _record;
+ public IntPtr _recordInfo;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct Blob
+ {
+ public int _size;
+ public IntPtr _data;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private unsafe struct Vector where T : unmanaged
+ {
+ public int _numElements;
+ public T* _data;
+
+ public Span AsSpan() => new(_data, _numElements);
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct VersionedStream
+ {
+ public Guid _version;
+ public IntPtr _stream;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ClipboardData
+ {
+ public uint _size;
+ public int _format;
+ public IntPtr _data;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private unsafe struct UnionTypes
+ {
+ [FieldOffset(0)] public sbyte _i1;
+ [FieldOffset(0)] public short _i2;
+ [FieldOffset(0)] public int _i4;
+ [FieldOffset(0)] public long _i8;
+ [FieldOffset(0)] public byte _ui1;
+ [FieldOffset(0)] public ushort _ui2;
+ [FieldOffset(0)] public uint _ui4;
+ [FieldOffset(0)] public ulong _ui8;
+ [FieldOffset(0)] public int _int;
+ [FieldOffset(0)] public uint _uint;
+ [FieldOffset(0)] public short _bool;
+ [FieldOffset(0)] public int _error;
+ [FieldOffset(0)] public float _r4;
+ [FieldOffset(0)] public double _r8;
+ [FieldOffset(0)] public long _cy;
+ [FieldOffset(0)] public double _date;
+ [FieldOffset(0)] public IntPtr _bstr;
+ [FieldOffset(0)] public IntPtr _unknown;
+ [FieldOffset(0)] public IntPtr _dispatch;
+ [FieldOffset(0)] public IntPtr _pvarVal;
+ [FieldOffset(0)] public IntPtr _byref;
+ [FieldOffset(0)] public Record _record;
+ [FieldOffset(0)] public Blob _blob;
+ [FieldOffset(0)] public VersionedStream* _versionedStream;
+ [FieldOffset(0)] public ClipboardData* clipboardData;
+ }
+
+ ///
+ /// Release resources owned by this instance.
+ ///
+ public unsafe void Dispose()
+ {
+#if TARGET_WINDOWS
+ fixed (void* pThis = &this)
+ {
+ // We are using PropVariantClear instead of VariantClear
+ // as PropVariantClear covers more cases (like VT_BLOB, VT_STREAM, VT_CF, etc.)
+ // than VariantClear does. We intend for users to be able to use this ComVariant type for
+ // both VARIANT and PROPVARIANT scenarios, so we need to support all of the variant kinds that might be set.
+ Interop.Ole32.PropVariantClear((nint)pThis);
+ }
+#else
+ // Re-implement the same clearing semantics as PropVariantClear manually for non-Windows platforms.
+ if (VarType == VarEnum.VT_BSTR)
+ {
+ Marshal.FreeBSTR(_typeUnion._unionTypes._bstr);
+ }
+ else if (VarType.HasFlag(VarEnum.VT_ARRAY))
+ {
+ throw new PlatformNotSupportedException(SR.ComVariant_SafeArray_PlatformNotSupported);
+ }
+ else if (VarType == VarEnum.VT_UNKNOWN || VarType == VarEnum.VT_DISPATCH)
+ {
+ if (_typeUnion._unionTypes._unknown != IntPtr.Zero)
+ {
+ Marshal.Release(_typeUnion._unionTypes._unknown);
+ }
+ }
+ else if (VarType == VarEnum.VT_RECORD)
+ {
+ if (_typeUnion._unionTypes._record._recordInfo != IntPtr.Zero)
+ {
+ // Invoke RecordClear on the record info with the data.
+ if (_typeUnion._unionTypes._record._record != IntPtr.Zero)
+ {
+ Marshal.ThrowExceptionForHR(((delegate* unmanaged)(*(*(void***)_typeUnion._unionTypes._record._recordInfo + 4 /* IRecordInfo.RecordClear slot */)))(_typeUnion._unionTypes._record._recordInfo, _typeUnion._unionTypes._record._record));
+ }
+ Marshal.Release(_typeUnion._unionTypes._record._recordInfo);
+ }
+ }
+ else if (VarType == VarEnum.VT_LPSTR || VarType == VarEnum.VT_LPWSTR || VarType == VarEnum.VT_CLSID)
+ {
+ Marshal.FreeCoTaskMem(_typeUnion._unionTypes._byref);
+ }
+ else if (VarType == VarEnum.VT_BLOB || VarType == VarEnum.VT_BLOB_OBJECT)
+ {
+ Marshal.FreeCoTaskMem(_typeUnion._unionTypes._blob._data);
+ }
+ else if (VarType == VarEnum.VT_STREAM || VarType == VarEnum.VT_STREAMED_OBJECT || VarType == VarEnum.VT_STORAGE || VarType == VarEnum.VT_STORED_OBJECT)
+ {
+ if (_typeUnion._unionTypes._unknown != IntPtr.Zero)
+ {
+ Marshal.Release(_typeUnion._unionTypes._unknown);
+ }
+ }
+ else if (VarType == VT_VERSIONED_STREAM)
+ {
+ VersionedStream* versionedStream = _typeUnion._unionTypes._versionedStream;
+ if (versionedStream != null && versionedStream->_stream != IntPtr.Zero)
+ {
+ Marshal.Release(versionedStream->_stream);
+ }
+ Marshal.FreeCoTaskMem((nint)versionedStream);
+ }
+ else if (VarType == VarEnum.VT_CF)
+ {
+ ClipboardData* clipboardData = _typeUnion._unionTypes.clipboardData;
+ if (clipboardData != null)
+ {
+ Marshal.FreeCoTaskMem(clipboardData->_data);
+ Marshal.FreeCoTaskMem((nint)clipboardData);
+ }
+ }
+ else if (VarType.HasFlag(VarEnum.VT_VECTOR))
+ {
+ switch (VarType & ~VarEnum.VT_VECTOR)
+ {
+ case VarEnum.VT_BSTR:
+ foreach (var str in GetRawDataRef>().AsSpan())
+ {
+ Marshal.FreeBSTR(str);
+ }
+ break;
+ case VarEnum.VT_LPSTR:
+ case VarEnum.VT_LPWSTR:
+ foreach (var str in GetRawDataRef>().AsSpan())
+ {
+ Marshal.FreeCoTaskMem(str);
+ }
+ break;
+ case VarEnum.VT_CF:
+ foreach (var cf in GetRawDataRef>().AsSpan())
+ {
+ Marshal.FreeCoTaskMem(cf._data);
+ }
+ break;
+ case VarEnum.VT_VARIANT:
+ foreach (var variant in GetRawDataRef>().AsSpan())
+ {
+ variant.Dispose();
+ }
+ break;
+ default:
+ break;
+ }
+ Marshal.FreeCoTaskMem((nint)GetRawDataRef>()._data);
+ }
+
+ // Clear out this ComVariant instance.
+ this = default;
+#endif
+ }
+
+#pragma warning disable CS0618 // We support the obsolete CurrencyWrapper type
+ ///
+ /// Create an instance from the specified value.
+ ///
+ /// The type of the specified value.
+ /// The value to wrap in an .
+ /// An that contains the provided value.
+ /// When does not directly correspond to a variant type.
+ public static ComVariant Create([DisallowNull] T value)
+ {
+ Unsafe.SkipInit(out ComVariant variant);
+ if (typeof(T) == typeof(DBNull))
+ {
+ variant = Null;
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ variant.VarType = VarEnum.VT_I2;
+ variant._typeUnion._unionTypes._i2 = (short)(object)value;
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ variant.VarType = VarEnum.VT_I4;
+ variant._typeUnion._unionTypes._i4 = (int)(object)value;
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ variant.VarType = VarEnum.VT_R4;
+ variant._typeUnion._unionTypes._r4 = (float)(object)value;
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ variant.VarType = VarEnum.VT_R8;
+ variant._typeUnion._unionTypes._r8 = (double)(object)value;
+ }
+ else if (typeof(T) == typeof(CurrencyWrapper))
+ {
+ variant.VarType = VarEnum.VT_CY;
+ variant._typeUnion._unionTypes._cy = decimal.ToOACurrency(((CurrencyWrapper)(object)value).WrappedObject);
+ }
+ else if (typeof(T) == typeof(DateTime))
+ {
+ variant.VarType = VarEnum.VT_DATE;
+ variant._typeUnion._unionTypes._date = ((DateTime)(object)value).ToOADate();
+ }
+ else if (typeof(T) == typeof(BStrWrapper))
+ {
+ variant.VarType = VarEnum.VT_BSTR;
+ variant._typeUnion._unionTypes._bstr = Marshal.StringToBSTR(((BStrWrapper)(object)value).WrappedObject);
+ }
+ else if (typeof(T) == typeof(string))
+ {
+ // We map string to VT_BSTR as that's the only valid option for a VARIANT.
+ // The rest of the "string" options are only supported in TYPEDESCs and PROPVARIANTs,
+ // which are different scenarios.
+ // Users who want to use the ComVariant type with VT_LPSTR or VT_LPWSTR can use CreateRaw
+ // to do so.
+ variant.VarType = VarEnum.VT_BSTR;
+ variant._typeUnion._unionTypes._bstr = Marshal.StringToBSTR((string)(object)value);
+ }
+ else if (typeof(T) == typeof(ErrorWrapper))
+ {
+ variant.VarType = VarEnum.VT_ERROR;
+ variant._typeUnion._unionTypes._error = ((ErrorWrapper)(object)value).ErrorCode;
+ }
+ else if (typeof(T) == typeof(bool))
+ {
+ // bool values in OLE VARIANTs are VARIANT_BOOL values.
+ variant.VarType = VarEnum.VT_BOOL;
+ variant._typeUnion._unionTypes._bool = ((bool)(object)value) ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+ else if (typeof(T) == typeof(decimal))
+ {
+ // Set the value first and then the type as the decimal storage
+ // overlaps with the type descriminator.
+ variant._decimal = (decimal)(object)value;
+ variant.VarType = VarEnum.VT_DECIMAL;
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ variant.VarType = VarEnum.VT_I1;
+ variant._typeUnion._unionTypes._i1 = (sbyte)(object)value;
+ }
+ else if (typeof(T) == typeof(byte))
+ {
+ variant.VarType = VarEnum.VT_UI1;
+ variant._typeUnion._unionTypes._ui1 = (byte)(object)value;
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ variant.VarType = VarEnum.VT_UI2;
+ variant._typeUnion._unionTypes._ui2 = (ushort)(object)value;
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ variant.VarType = VarEnum.VT_UI4;
+ variant._typeUnion._unionTypes._ui4 = (uint)(object)value;
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ variant.VarType = VarEnum.VT_I8;
+ variant._typeUnion._unionTypes._i8 = (long)(object)value;
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ variant.VarType = VarEnum.VT_UI8;
+ variant._typeUnion._unionTypes._ui8 = (ulong)(object)value;
+ }
+ else
+ {
+ throw new ArgumentException(SR.UnsupportedType, nameof(T));
+ }
+ // We do not support mapping nint or nuint to VT_INT and VT_UINT respectively
+ // as this does not match the MS-OAUT spec.
+ // We do not map VT_BYREF automatically, nor do we map any of the array types.
+ return variant;
+ }
+#pragma warning restore CS0618
+
+ ///
+ /// Create a with the given type and provided value.
+ ///
+ /// The type of the value to store in the variant.
+ /// The type of the variant
+ /// The raw value to store in the variant without any processing
+ /// A variant that contains the provided value.
+ /// When the provided corresponds to a variant type that is not supported in VARIANTs or is
+ /// When the provided specifies the flag for SAFEARRAYs.
+ public static unsafe ComVariant CreateRaw(VarEnum vt, T rawValue)
+ where T : unmanaged
+ {
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(Unsafe.SizeOf(), sizeof(UnionTypes), nameof(T));
+ if (vt == VarEnum.VT_DECIMAL)
+ {
+ throw new ArgumentException(SR.ComVariant_VT_DECIMAL_NotSupported_CreateRaw, nameof(vt));
+ }
+ if (vt == VarEnum.VT_VARIANT)
+ {
+ throw new ArgumentException(SR.ComVariant_VT_VARIANT_In_Variant, nameof(vt));
+ }
+ if (vt.HasFlag(VarEnum.VT_ARRAY) && !OperatingSystem.IsWindows())
+ {
+ throw new PlatformNotSupportedException(SR.ComVariant_SafeArray_PlatformNotSupported);
+ }
+
+ Unsafe.SkipInit(out ComVariant value);
+ value.VarType = vt;
+ value.GetRawDataRef() = (vt, sizeof(T)) switch
+ {
+ (VarEnum.VT_I1 or VarEnum.VT_UI1, 1) => rawValue,
+ (VarEnum.VT_I2 or VarEnum.VT_UI2 or VarEnum.VT_BOOL, 2) => rawValue,
+ (VarEnum.VT_ERROR or VarEnum.VT_HRESULT or VarEnum.VT_I4 or VarEnum.VT_UI4 or VarEnum.VT_R4 or VarEnum.VT_INT or VarEnum.VT_UINT, 4) => rawValue,
+ (VarEnum.VT_I8 or VarEnum.VT_UI8 or VarEnum.VT_R8 or VarEnum.VT_DATE, 8) => rawValue,
+ (VarEnum.VT_UNKNOWN or VarEnum.VT_DISPATCH or VarEnum.VT_LPSTR or VarEnum.VT_BSTR or VarEnum.VT_LPWSTR or VarEnum.VT_SAFEARRAY
+ or VarEnum.VT_CLSID or VarEnum.VT_STREAM or VarEnum.VT_STREAMED_OBJECT or VarEnum.VT_STORAGE or VarEnum.VT_STORED_OBJECT or VarEnum.VT_CF or VT_VERSIONED_STREAM, _) when sizeof(T) == nint.Size => rawValue,
+ (VarEnum.VT_CY or VarEnum.VT_FILETIME, 8) => rawValue,
+ (VarEnum.VT_RECORD, _) when sizeof(T) == sizeof(Record) => rawValue,
+ _ when vt.HasFlag(VarEnum.VT_BYREF) && sizeof(T) == nint.Size => rawValue,
+ _ when vt.HasFlag(VarEnum.VT_VECTOR) && sizeof(T) == sizeof(Vector) => rawValue,
+ _ when vt.HasFlag(VarEnum.VT_ARRAY) && sizeof(T) == nint.Size => rawValue,
+ (VarEnum.VT_BLOB or VarEnum.VT_BLOB_OBJECT, _) when sizeof(T) == sizeof(Blob) => rawValue,
+ _ => throw new ArgumentException(SR.Format(SR.ComVariant_SizeMustMatchVariantSize, nameof(T), nameof(vt)))
+ };
+
+ return value;
+ }
+
+ ///
+ /// A instance that represents a null value with type.
+ ///
+ public static ComVariant Null { get; } = new() { VarType = VarEnum.VT_NULL };
+
+ private readonly void ThrowIfNotVarType(params VarEnum[] requiredType)
+ {
+ if (Array.IndexOf(requiredType, VarType) == -1)
+ {
+ throw new InvalidOperationException(SR.Format(SR.ComVariant_TypeIsNotSupportedType, VarType, string.Join(", ", requiredType)));
+ }
+ }
+
+#pragma warning disable CS0618 // Type or member is obsolete
+ ///
+ /// Create a managed value based on the value in the instance.
+ ///
+ /// The managed type to create an instance of.
+ /// The managed value contained in this variant.
+ /// When does not match the of the .
+ public readonly T? As()
+ {
+ if (VarType == VarEnum.VT_EMPTY)
+ {
+ return default;
+ }
+ if (typeof(T) == typeof(DBNull))
+ {
+ ThrowIfNotVarType(VarEnum.VT_NULL);
+ return (T)(object)DBNull.Value;
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ ThrowIfNotVarType(VarEnum.VT_I2);
+ return (T)(object)_typeUnion._unionTypes._i2;
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ ThrowIfNotVarType(VarEnum.VT_I4, VarEnum.VT_ERROR, VarEnum.VT_INT);
+ return (T)(object)_typeUnion._unionTypes._i4;
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ ThrowIfNotVarType(VarEnum.VT_R4);
+ return (T)(object)_typeUnion._unionTypes._r4;
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ ThrowIfNotVarType(VarEnum.VT_R8);
+ return (T)(object)_typeUnion._unionTypes._r8;
+ }
+ else if (typeof(T) == typeof(CurrencyWrapper))
+ {
+ ThrowIfNotVarType(VarEnum.VT_CY);
+ return (T)(object)new CurrencyWrapper(decimal.FromOACurrency(_typeUnion._unionTypes._cy));
+ }
+ else if (typeof(T) == typeof(DateTime))
+ {
+ ThrowIfNotVarType(VarEnum.VT_DATE);
+ return (T)(object)DateTime.FromOADate(_typeUnion._unionTypes._date);
+ }
+ else if (typeof(T) == typeof(BStrWrapper))
+ {
+ ThrowIfNotVarType(VarEnum.VT_BSTR);
+ return (T)(object)new BStrWrapper(Marshal.PtrToStringBSTR(_typeUnion._unionTypes._bstr));
+ }
+ else if (typeof(T) == typeof(string))
+ {
+ // To match the Create method, we will only support getting a string from an ComVariant
+ // when the ComVariant holds a BSTR.
+ ThrowIfNotVarType(VarEnum.VT_BSTR);
+ if (_typeUnion._unionTypes._bstr == IntPtr.Zero)
+ {
+ return default;
+ }
+ return (T)(object)Marshal.PtrToStringBSTR(_typeUnion._unionTypes._bstr);
+ }
+ else if (typeof(T) == typeof(ErrorWrapper))
+ {
+ ThrowIfNotVarType(VarEnum.VT_ERROR);
+ return (T)(object)new ErrorWrapper(_typeUnion._unionTypes._error);
+ }
+ else if (typeof(T) == typeof(bool))
+ {
+ // bool values in OLE VARIANTs are VARIANT_BOOL values.
+ ThrowIfNotVarType(VarEnum.VT_BOOL);
+ return (T)(object)(_typeUnion._unionTypes._bool != VARIANT_FALSE);
+ }
+ else if (typeof(T) == typeof(decimal))
+ {
+ // Set the value first and then the type as the decimal storage
+ // overlaps with the type descriminator.
+ ThrowIfNotVarType(VarEnum.VT_DECIMAL);
+ // Create a second variant copy with the VarType set to VT_EMPTY.
+ // This will ensure that we don't leak the VT_DECMIAL flag into the decimal value itself.
+ ComVariant variantWithoutVarType = this;
+ variantWithoutVarType.VarType = VarEnum.VT_EMPTY;
+ return (T)(object)variantWithoutVarType._decimal;
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ ThrowIfNotVarType(VarEnum.VT_I1);
+ return (T)(object)_typeUnion._unionTypes._i1;
+ }
+ else if (typeof(T) == typeof(byte))
+ {
+ ThrowIfNotVarType(VarEnum.VT_UI1);
+ return (T)(object)_typeUnion._unionTypes._ui1;
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ ThrowIfNotVarType(VarEnum.VT_UI2);
+ return (T)(object)_typeUnion._unionTypes._ui2;
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ ThrowIfNotVarType(VarEnum.VT_UI4, VarEnum.VT_UINT);
+ return (T)(object)_typeUnion._unionTypes._ui4;
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ ThrowIfNotVarType(VarEnum.VT_I8);
+ return (T)(object)_typeUnion._unionTypes._i8;
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ ThrowIfNotVarType(VarEnum.VT_UI8);
+ return (T)(object)_typeUnion._unionTypes._ui8;
+ }
+ throw new ArgumentException(SR.UnsupportedType, nameof(T));
+ }
+#pragma warning restore CS0618 // Type or member is obsolete
+
+ ///
+ /// The type of the data stored in this .
+ ///
+ public VarEnum VarType
+ {
+ readonly get => (VarEnum)_typeUnion._vt;
+ private set => _typeUnion._vt = (ushort)value;
+ }
+
+ ///
+ /// Get a reference to the storage location within this instance.
+ ///
+ /// The type of reference to return.
+ /// A reference to the storage location within this .
+ /// is or larger than the storage space in an .
+ [UnscopedRef]
+ public unsafe ref T GetRawDataRef()
+ where T : unmanaged
+ {
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(Unsafe.SizeOf(), sizeof(UnionTypes), nameof(T));
+ if (typeof(T) == typeof(decimal))
+ {
+ throw new ArgumentException(SR.ComVariant_VT_DECIMAL_NotSupported_RawDataRef, nameof(T));
+ }
+ return ref Unsafe.As(ref _typeUnion._unionTypes);
+ }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs
index d386e1c299ee67..500960104fb4a0 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs
@@ -1553,152 +1553,152 @@ internal Arm64() { }
///
/// A64: LD2 { Vn.16B, Vn+1.16B }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(15))] byte index, byte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(15))] byte index, byte* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.16B, Vn+1.16B }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(15))] byte index, sbyte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(15))] byte index, sbyte* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.8H, Vn+1.8H }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(7))] byte index, short* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(7))] byte index, short* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.8H, Vn+1.8H }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(7))] byte index, ushort* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(7))] byte index, ushort* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.4S, Vn+1.4S }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, int* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, int* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.4S, Vn+1.4S }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, uint* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, uint* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.2D, Vn+1.2D }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, long* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, long* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.2D, Vn+1.2D }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, ulong* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, ulong* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.4S, Vn+1.4S }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, float* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(3))] byte index, float* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD2 { Vn.2D, Vn+1.2D }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, double* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2) LoadAndInsertScalar((Vector128, Vector128) values, [ConstantExpected(Max = (byte)(1))] byte index, double* address) { throw new PlatformNotSupportedException(); }
///
/// A64: LD3 { Vn.16B, Vn+1.16B, Vn+2.16B }[Vm], [Xn]
///
- public static unsafe (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2, System.Runtime.Intrinsics.Vector128 Value3) LoadAndInsertScalar((System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) values, [ConstantExpected(Max = (byte)(15))] byte index, byte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe (Vector128 Value1, Vector128 Value2, Vector128 Value3) LoadAndInsertScalar((Vector128, Vector128